摘要:基本類型類對象純對象類數組其中部分參考了的函數實現。比如說所以如果此時對象不是由內置構造函數生成的對象,這個為。判斷對于類數組對象,只要該對象中存在屬性并且為非負整數且在有限范圍之內即可判斷為類數組對象。
本文主要講解如何準確判斷JavaScript中出現的各種類型和對象。(基本類型、Object類、Window對象、純對象plainObject、類數組)其中部分參考了jQuery的函數實現。typeof
JavaScript定義的數據類型有Undefined、Null、Boolean、Number、String、Object、Symbol(ES6新增)。
其中typeof對大部分的數據類型都能夠準確識別,如下:
typeof undefined // "undefined" typeof null // "object" typeof true // "boolean" typeof 1 // "number" typeof "s" // "string" typeof {} // "object" typeof function a() {} // "function" typeof Symbol("2") // "symbol"
其中返回的字符串首字母都是小寫的。
對于typeof null === "object"來說,這其實是一個bug。
在JavaScript中,Object下還有很多細分的類型,比如說Date、RegExp、Error、Array、Function。
typeof除了能夠準確的判斷出Function之外,對于其他細分類型均返回object。
Object.prototype.toString()當toString方法被調用的時候,下面的步驟會被執行:
如果this值是undefined,就返回[object Undefined]
如果this的值是null,就返回[object Null]
讓O成為ToObject(this)的結果
讓class成為O的內部屬性[[Class]]的值
最后返回由"[object "和class和"]"三個部分組成的字符串
該方法至少可以識別14種類型。
// 以下是11種: var number = 1; // [object Number] var string = "123"; // [object String] var boolean = true; // [object Boolean] var und = undefined; // [object Undefined] var nul = null; // [object Null] var obj = {a: 1} // [object Object] var array = [1, 2, 3]; // [object Array] var date = new Date(); // [object Date] var error = new Error(); // [object Error] var reg = /a/g; // [object RegExp] var func = function a(){}; // [object Function] function checkType() { for (var i = 0; i < arguments.length; i++) { console.log(Object.prototype.toString.call(arguments[i])) } } checkType(number, string, boolean, und, nul, obj, array, date, error, reg, func) // 還有不常見的Math、JSON console.log(Object.prototype.toString.call(Math)); // [object Math] console.log(Object.prototype.toString.call(JSON)); // [object JSON] // 還有一個arguments function a() { console.log(Object.prototype.toString.call(arguments)); // [object Arguments] } a();type API
結合上面我們可以寫一個type函數,其中基本類型值走typeof,引用類型值走toString。
var class2type = {}; // 生成class2type映射 "Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) { class2type["[object " + item + "]"] = item.toLowerCase(); }) function type(obj) { // 一箭雙雕 if (obj == null) { return obj + ""; } return typeof obj === "object" || typeof obj === "function" ? class2type[Object.prototype.toString.call(obj)] || "object" : typeof obj; }
通過toLowerCase()小寫化和typeof的結果是小寫一致。
注意IE6中toString()會把Undefined和Null都識別為[object Object],所以加了一個判斷,直接調用+來隱式toString()-> "null"。
這里之所以class2type[Object.prototype.toString.call(obj)] || "object"是考慮到ES6新增的Symbol、Map、Set在集合class2type中沒有,直接把他們識別成object。
這個type其實就是jQuery中的type。
isFunction之后可以直接封裝:
function isFunction(obj) { return type(obj) === "function"; }數組
var isArray = Array.isArray || function( obj ) { return type(obj) === "array"; }
jQuery3.0中已經完全使用Array.isArray()。
plainObjectplainObject翻譯為中文即為純對象,所謂的純對象,就是該對象是通過{}或new Object()創建的。
判斷是否為“純對象”,是為了和其他對象區分開比如說null、數組以及宿主對象(所有的DOM和BOM都是數組對象)等。
jQuery中有提供了該方法的實現,除了規定該對象是通過{}或new Object()創建的,且對象含有零個或者多個鍵值對外,一個沒有原型(__proto__)的對象也是一個純對象。
console.log($.isPlainObject({})) // true console.log($.isPlainObject(new Object)) // true console.log($.isPlainObject(Object.create(null))); // true
jQuery3.0版本的plainObject實現如下:
var toString = Object.prototype.toString; var hasOwn = Object.prototype.hasOwnProperty; function isPlainObject(obj) { var proto, Ctor; // 排除掉明顯不是obj的以及一些宿主對象如Window if (!obj || toString.call(obj) !== "[object Object]") { return false; } /** * getPrototypeOf es5 方法,獲取 obj 的原型 * 以 new Object 創建的對象為例的話 * obj.__proto__ === Object.prototype */ proto = Object.getPrototypeOf(obj); // 沒有原型的對象是純粹的,Object.create(null) 就在這里返回 true if (!proto) { return true; } /** * 以下判斷通過 new Object 方式創建的對象 * 判斷 proto 是否有 constructor 屬性,如果有就讓 Ctor 的值為 proto.constructor * 如果是 Object 函數創建的對象,Ctor 在這里就等于 Object 構造函數 */ Ctor = hasOwn.call(proto, "constructor") && proto.constructor; // 在這里判斷 Ctor 構造函數是不是 Object 構造函數,用于區分自定義構造函數和 Object 構造函數 return typeof Ctor === "function" && hasOwn.toString.call(Ctor) === hasOwn.toString.call(Object); }
注意最后這一句非常的重要:
hasOwn.toString.call(Ctor) === hasOwn.toString.call(Object)
hasOwn.toString調用的其實是Function.prototype.toString()而不是Object.prototype.toString(),因為hasOwnProperty是一個函數,它的原型是Function,于是Function.prototype.toString覆蓋了Object.prototype.toString。
Function.prototype.toString()會把整個函數體轉換成一個字符串。如果該函數是內置函數的話,會返回一個表示函數源代碼的字符串。比如說:
Function.prototype.toString(Object) === function Object() { [native code] }
所以如果此時對象不是由內置構造函數生成的對象,這個hasOwn.toString.call(Ctor) === hasOwn.toString.call(Object)為false。
function Person(name) { this.name = name; } var person = new Person("Devin"); plainObject(person) === false; // true // 其實就是`hasOwn.toString.call(Ctor) === "function Person(name) { this.name = name; }"Window對象
Window對象有一個特性:Window.window指向自身。
Window.window === Window; //true類數組對象
常見的類數組有函數的arguments和NodeList對象。
判斷對于類數組對象,只要該對象中存在length屬性并且length為非負整數且在有限范圍之內即可判斷為類數組對象。
JavaScript權威指南中提供了方法:
function isArrayLike(o) { if (o && // o is not null, undefined, etc // o is an object typeof o === "object" && // o.length is a finite number isFinite(o.length) && // o.length is non-negative o.length >= 0 && // o.length is an integer o.length === Math.floor(o.length) && // o.length < 2^32 o.length < 4294967296) //數組的上限值 return true; else return false; }
以上的判斷無論是真的數組對象或是類數組對象都會返回true,那我們如何區分到底是真的數組對象還是類數組對象?
其實只需要先判斷是否為數組對象即可。
function utilArray(o) { if (Array.isArray(o)) { return "array"; } if (isArrayLike(o)) { return "arrayLike"; } else { return "neither array nor arrayLike"; } }類數組對象的特征
類數組對象并不關心除了數字索引和length以外的東西。
比如說:
var a = {"1": "a", "2": "b", "4": "c", "abc": "abc", length: 5}; Array.prototype.join.call(a, "+"); // +a+b++c
其中,"0"和"3"沒有直接省略為兩個undefined,同樣的abc被忽略為undefined。
如果length多出實際的位數會補undefined(空位也補充undefined),少位則截斷后面的數組成員。
var a = {"1": "a", "2": "b", "4": "c", "abc": "abc", length: 6}; Array.from(a); // [undefined, "a", "b", undefined, "c", undefined] var a = {"1": "a", "2": "b", "4": "c", "abc": "abc", length: 5}; Array.from(a); // [undefined, "a", "b", undefined, "c"] var a = {"1": "a", "2": "b", "4": "c", "abc": "abc", length: 4}; Array.from(a); // [undefined, "a", "b", undefined]類數組對象的轉換
Array.from
該方法從一個類似數組或可迭代對象中創建一個新的數組實例。
Array.from("foo"); // ["f", "o", "o"]
Array.prototype.slice
該方法返回一個從開始到結束(不包括結束)選擇的數組的一部分淺拷貝到一個新數組對象。
var a = {"0":"a", "1":"b", "2":"c", length: 3}; Array.prototype.slice.call(a, 0); // ["a", "b", "c"]
ES6擴展運算符
var a = "hello"; [...a]; //["h", "e", "l", "l", "o"]
參考鏈接:
https://github.com/mqyqingfen...
https://github.com/mqyqingfen...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107601.html
摘要:判斷變量類型數據類型種操作符可能返回的值如下注意的能力有限,其對于類型返回的都是使用場景區分對象和原始類型要區分一種對象類型和另一種對象類型可以使用運算符或對象屬性運算符用法左邊的運算數是一個右邊運算數是對象類的名字或者構造函數返回或如果是 判斷變量類型 javaSctipt數據類型7種: Number, String, Boolean, Null, Undefined, Object...
摘要:不過讓流行起來的原因應該是是目前所有主流瀏覽器上唯一支持的腳本語言。經過測試,數字字符串布爾日期可以直接賦值,修改不會產生影響。再考慮對象類型為或者的情況。對于結果聲明其類型。判斷對象的類型是還是,結果類型更改。 轉載自我的個人博客 歡迎大家批評指正 1. 第一個頁面交互 這里最需要學習的老師的代碼中,每一部分功能都由函數控制,沒有創建一個全部變量。且最后有一個函數來控制執行代碼...
摘要:語法部分屬性默認的就是,所以不必顯式指定為。不強制在每個語句結尾加,會自動加分號,但是在某些情況下會改變程序的語義,所以最好主動加。實際上,默認有一個全局對象。 語法部分: 1.type 屬性: 默認的 type 就是 javascript, 所以不必顯式指定 type 為 javascript。2.javascript 不強制在每個語句結尾加 ; , javascript 會自...
摘要:類型的實例首先要理解的含義是例子的意思,實際上是判斷是否是的一個實例。 數據類型深入理解 數據類型分類 基本(值)類型(5種) String:任意字符串 Number:任意的數字 boolean:true/false null:null undefined:undefined 對象(引用)類型(3種) Object:任意對象 Array:一種特別的對象(數值下...
摘要:判斷是否為一個函數,返回一個值。使用遞歸來實現一個深度克隆,可以復制一個目標對象,返回一個完整拷貝被復制的對象類型會被限制為數字字符串布爾日期數組對象。經過測試,數字字符串布爾日期可以直接賦值,修改不會產生影響。再考慮對象類型為或者的情況。 //判斷arr是否為一個數組,返回一個bool值 首先javascript有5大基本數據類型:Undefined,Null,Boolean,Num...
摘要:內置函數和對象中內置了一些函數和對象,很多語言都會有內置的方法,直接可以調用開發。根據語法標準提供的內置函數包括和。注意基礎語法提供的內置函數和方法只有這些,像那是瀏覽器提供給我們的。強制類型轉換大家應該都知道。 js基礎 - 變量 *大家對js一定不會陌生,入門很簡單(普通入門),很多人通過網絡資源、書籍、課堂等很多途徑學習js,但是有些js基礎的只是往往被大家遺漏,本章就從js變量...
閱讀 3382·2021-11-22 13:53
閱讀 3422·2021-10-11 11:11
閱讀 937·2019-08-30 14:12
閱讀 1227·2019-08-29 17:16
閱讀 647·2019-08-29 16:45
閱讀 3359·2019-08-29 12:56
閱讀 676·2019-08-28 17:55
閱讀 2071·2019-08-26 13:24