簡單談?wù)凧avascript中類型的判斷
數(shù)據(jù)類型的判斷有這么幾種方式
1、一元運算符 typeOf
2、關(guān)系運算符 instanceof
3、constructor 屬性
4、prototype屬性
一、typeof
typeof的返回值有以下幾種
| 類型 | 結(jié)構(gòu) |
|---|---|
| Undefined | "undefined" |
| Null | "object" (見下方) |
| 布爾值 | "boolean" |
| 數(shù)值 | "number" |
| 字符串 | "string" |
| Symbol (ECMAScript 6 新增) | "symbol" |
| 宿主對象(JS環(huán)境提供的,比如瀏覽器) | Implementation-dependent |
| 函數(shù)對象 (implements [[Call]] in ECMA-262 terms) | "function" |
| 任何其他對象 | "object" |
簡單粗暴的方法,直接看代碼
// 以下代碼在版本 Google Chrome 45.0.2454.101 m 中測試通過
// Numbers
console.log(typeof 37 === 'number');
console.log(typeof 3.14 === 'number');
console.log(typeof Math.LN2 === 'number');
console.log(typeof Infinity === 'number');
console.log(typeof NaN === 'number'); // 盡管NaN是"Not-A-Number"的縮寫,意思是"不是一個數(shù)字"
console.log(typeof Number(1) === 'number'); // 不要這樣使用!
// Strings
console.log(typeof "" === 'string');
console.log(typeof "bla" === 'string');
console.log(typeof (typeof 1) === 'string'); // console.log(typeof返回的肯定是一個字符串
console.log(typeof String("abc") === 'string'); // 不要這樣使用!
// Booleans
console.log(typeof true === 'boolean');
console.log(typeof false === 'boolean');
console.log(typeof Boolean(true) === 'boolean'); // 不要這樣使用!
// Symbols
console.log(typeof Symbol() === 'symbol');
console.log(typeof Symbol('foo') === 'symbol');
console.log(typeof Symbol.iterator === 'symbol');
// Undefined
console.log(typeof undefined === 'undefined');
console.log(typeof blabla === 'undefined'); // 一個未定義的變量,或者一個定義了卻未賦初值的變量
// Objects 使用Array.isArray或者Object.prototype.toString.call方法可以從基本的對象中區(qū)分出數(shù)組類型
console.log(typeof {a:1} === 'object');
console.log(typeof [1, 2, 4] === 'object');
console.log(typeof /^[a-zA-Z]{5,20}$/ === 'object');
console.log(typeof {name:'wenzi', age:25} === 'object');
console.log(typeof null === 'object');//true
// 下面的容易令人迷惑,不要這樣使用!
console.log(typeof new Boolean(true) === 'object');
console.log(typeof new Number(1) === 'object');
console.log(typeof new Date() === 'object');
console.log(typeof new String("abc") === 'object');
console.log(typeof new Error() === 'object');
// 函數(shù)
console.log(typeof function(){} === 'function');
console.log(typeof Math.sin === 'function');
typeof 只能檢查出來以上7幾種類型
二、instanceof
instanceof 運算符用于識別正在處理的對象的類型,要求開發(fā)者明確地確認對象為某特定類型
1、instanceof 和 constructor 沒有關(guān)系
var A = function() {};
A.prototype = {};
var B = {};
console.log(A.constructor);//function Function() { [native code] }
console.log(B.constructor);//function Object() { [native code] }
var a = new A();
A.prototype = {};
var b = new A();
b.constructor = A.constructor;
console.log(a.constructor === A);//false
console.log(a.constructor);//function Object() { [native code] }
console.log(typeof A);//function Object() { [native code] }
console.log(a.constructor === b.constructor);//false
console.log(b.constructor);//function Function() { [native code] }
console.log(a instanceof A);//false
console.log(b instanceof A);//true
2、instanceof又叫關(guān)系運算符,可以用來判斷某個構(gòu)造函數(shù)的prototype屬性是否存在另外一個要檢測對象的原型鏈上
var str = new String("hello world");
console.log(str instanceof String);//true
console.log(String instanceof Function);//true
console.log(str instanceof Function);//false
第三次輸出為什么會返回false呢 ?原文地址:Javascript中一個關(guān)于instanceof的問題
//表達式一的指向 console.log(str.__proto__ === String.prototype);//true console.log(str instanceof String); //true //表達式二的指向 console.log(String .__proto__ === Function.prototype);//true console.log(String instanceof Function);//true //表達式三的指向 console.log(str .__proto__ === String.prototype);//true console.log(str .__proto__.__proto__ === String.prototype.__proto__);//true console.log(str .__proto__.__proto__ === Object.prototype);//true console.log(str .__proto__.__proto__.__proto__ === null);//true console.log(str instanceof Object);//true console.log(str instanceof Function);//false
再看一個復(fù)雜的用法
console.log(Object instanceof Object);//true console.log(Function instanceof Function);//true console.log(Number instanceof Number);//false console.log(String instanceof String);//false console.log(Function instanceof Object);//true console.log(Foo instanceof Function);//true console.log(Foo instanceof Foo);//false
為什么,這是為什么呢,要搞明白以下含義
1、語言規(guī)范中是如何定義這個運算符的
2、JavaScript 原型繼承機制
Object instanceof Object
// 為了方便表述,首先區(qū)分左側(cè)表達式和右側(cè)表達式 ObjectL = Object, ObjectR = Object; console.log(ObjectL instanceof ObjectR);//true
// 下面根據(jù)規(guī)范逐步推演 console.log(ObjectL.__proto__ === Function.prototype); //true console.log(ObjectL.__proto__.__proto__ === Object.prototype);//true
Function instanceof Function
FunctionL = Function, FunctionR = Function;
console.log(FunctionL instanceof FunctionR);//true
console.log(FunctionL.__proto__ === Function.prototype); //true
Foo instanceof Foo
function Foo(){}
var foo = new Foo();
FooL = Foo, FooR = Foo;
console.log(FooL instanceof FooR);//false
console.log(FooL.__proto__ === Function.prototype );//true
console.log(FooL.__proto__.__proto__ === Object.prototype );//true
console.log(FooL.__proto__.__proto__.__proto__ === null );//true
instanceof 在 Dojo 繼承機制中的應(yīng)用
在 JavaScript 中,是沒有多重繼承這個概念的,就像 Java 一樣。但在 Dojo 中使用 declare 聲明類時,是允許繼承自多個類的
dojo.declare("Aoo",null,{});
dojo.declare("Boo",null,{});
dojo.declare("Foo",[Aoo,Boo],{});
var foo = new Foo();
console.log(foo instanceof Aoo);//true
console.log(foo instanceof Boo);//false
console.log(foo.isInstanceOf(Aoo));//true
console.log(foo.isInstanceOf(Boo));//true
instanceof和多全局對象(多個frame或多個window之間的交互)
在瀏覽器中,我們的腳本可能需要在多個窗口之間進行交互。多個窗口意味著多個全局環(huán)境,不同的全局環(huán)境擁有不同的全局對象,從而擁有不同的內(nèi)置類型構(gòu)造函數(shù)。這可能會引發(fā)一些問題。比如,表達式 [] instanceof window.frames[0].Array 會返回false,因為 Array.prototype !== window.frames[0].Array.prototype,因此你必須使用 Array.isArray(myObj) 或者Object.prototype.toString.call(myObj) === "[object Array]"來判斷myObj是否是數(shù)組。
// 以下代碼在版本 Google Chrome 45.0.2454.101 m 中測試通過
// Numbers
console.log(37 instanceof Number);//false
console.log( 3.14 instanceof Number);.//false
console.log( Math.LN2 instanceof Number);//false
console.log( Infinity instanceof Number);//false
console.log( NaN instanceof Number); // false盡管NaN是"Not-A-Number"的縮寫,意思是"不是一個數(shù)字"
console.log( Number(1) instanceof Number); // false不要這樣使用!
// Strings
console.log( "" instanceof String);// false
console.log( "bla" instanceof String);// false
console.log( ( 1) instanceof String); // falseconsole.log(返回的肯定是一個字符串
console.log( String("abc") instanceof String); // false 不要這樣使用!
// Booleans
console.log( true instanceof Boolean);// false
console.log( false instanceof Boolean);// false
console.log( Boolean(true) instanceof Boolean); //false 不要這樣使用!
// Symbols
console.log( Symbol() instanceof Symbol);// false
console.log( Symbol("foo") instanceof Symbol);// false
console.log( Symbol.iterator instanceof Symbol);// false
// Undefined
var blabla;
//console.log( undefined instanceof Undefined);// Uncaught ReferenceError: Undefined is not defined
//console.log( blabla instanceof Undefined); // Uncaught ReferenceError: Undefined is not defined
console.log( undefined instanceof Object);// false
console.log( blabla instanceof Object);// false
// Objects 使用Array.isArray或者Object.prototype.toString.call方法可以從基本的對象中區(qū)分出數(shù)組類型
console.log( {a:1} instanceof Object);//true
console.log( [1, 2, 4] instanceof Object);//true
console.log( /^[a-zA-Z]{5,20}$/ instanceof Object);//true
console.log( {name:'wenzi', age:25} instanceof Object);//true
console.log( null === Object);//false
// 下面的容易令人迷惑,不要這樣使用!
console.log( new Boolean(true) instanceof Object);//true
console.log( new Number(1) instanceof Object);//true
console.log( new Date() instanceof Object);//true
console.log( new String("abc") instanceof Object);//true
console.log( new Error() instanceof Object);//true
// 函數(shù)
console.log( function(){} instanceof Function );//true
console.log( Math.sin instanceof Function);//true
注意:undefined和null是檢測的Object類型,因為js中沒有Undefined和Null的這種全局類型,number, string和boolean無法檢測出它的類型
三、constructor
在使用instanceof檢測變量類型時,我們是檢測不到number, 'string', bool的類型的。因此,我們需要換一種方式來解決這個問題
Object.prototype.constructor返回一個指向創(chuàng)建了該對象原型的函數(shù)引用。需要注意的是,該屬性的值是那個函數(shù)本身,而不是一個包含函數(shù)名稱的字符串。對于原始值(如1,true 或 "test"),該屬性為只讀,所有對象都會從它的原型上繼承一個 constructor 屬性
constructor本來是原型對象上的屬性,指向構(gòu)造函數(shù)。但是根據(jù)實例對象尋找屬性的順序,若實例對象上沒有實例屬性或方法時,就去原型鏈上尋找,因此,實例對象也是能使用constructor屬性的
function Person(){
}
var Tom = new Person();
console.log(Tom.constructor === Person);//true
不過要注意,constructor屬性是可以被修改的,會導(dǎo)致檢測出的結(jié)果不正確
function Person(){
}
function Student(){
}
Student.prototype = new Person();
var John = new Student();
console.log(John.constructor==Student); // false
console.log(John.constructor==Person); // true
改變這個對象的constructor屬性的值
function Type() { };
var types = [
new Array,
[],
new Boolean,
true, // remains unchanged
new Date,
new Error,
new Function,
function(){},
Math,
new Number,
1, // remains unchanged
new Object,
{},
new RegExp,
/(?:)/,
new String,
"test" // remains unchanged
];
for(var i = 0; i < types.length; i++) {
types[i].constructor = Type;
types[i] = [ types[i].constructor, types[i] instanceof Type, types[i].toString() ];
};
console.log( types.join("\n") );
除了undefined和null,其他類型的變量均能使用constructor判斷出類型
四、萬能的Object.prototype.toString.call
使用toString()方法來檢測對象類型
function Type() { };
var toString = Object.prototype.toString;
console.log(toString.call(new Date) === '[object Date]');//true
console.log(toString.call(new String) ==='[object String]');//true
console.log(toString.call(new Function) ==='[object Function]');//true
console.log(toString.call(Type) ==='[object Function]');//true
console.log(toString.call('str') ==='[object String]');//true
console.log(toString.call(Math) === '[object Math]');//true
console.log(toString.call(true) ==='[object Boolean]');//true
console.log(toString.call(/^[a-zA-Z]{5,20}$/) ==='[object RegExp]');//true
console.log(toString.call({name:'wenzi', age:25}) ==='[object Object]');//true
console.log(toString.call([1, 2, 3, 4]) ==='[object Array]');//true
//Since JavaScript 1.8.5
console.log(toString.call(undefined) === '[object Undefined]');//true
console.log(toString.call(null) === '[object Null]');//true
附上判斷函數(shù) Javascript中的數(shù)據(jù)類型知多少
五、jquery的實現(xiàn) jquery: "1.8.2",
jquery中提供了一個$.type的接口,看看代碼
var m = Object.prototype.toString //501行
E = {};//512行
isFunction: function(a) { //645行
return p.type(a) === "function"
},
isArray: Array.isArray || function(a) {
return p.type(a) === "array"
}
,
isWindow: function(a) {
return a != null && a == a.window
},
isNumeric: function(a) {
return !isNaN(parseFloat(a)) && isFinite(a)
},
type: function(a) {
return a == null ? String(a) : E[m.call(a)] || "object"
},
isPlainObject: function(a) {
if (!a || p.type(a) !== "object" || a.nodeType || p.isWindow(a))
return !1;
try {
if (a.constructor && !n.call(a, "constructor") && !n.call(a.constructor.prototype, "isPrototypeOf"))
return !1
} catch (c) {
return !1
}
var d;
for (d in a)
;
return d === b || n.call(a, d)
},
isEmptyObject: function(a) {
var b;
for (b in a)
return !1;
return !0
},
可以看出來,jquery中就是用Object.prototype.toString.call實現(xiàn)的
相關(guān)文章
微信小程序?qū)崿F(xiàn)側(cè)邊欄二級聯(lián)動
這篇文章主要為大家詳細介紹了微信小程序?qū)崿F(xiàn)側(cè)邊欄二級聯(lián)動,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-07-07
網(wǎng)頁前端登錄js按Enter回車鍵實現(xiàn)登陸的兩種方法
下面小編就為大家?guī)硪黄W(wǎng)頁前端登錄js按Enter回車鍵實現(xiàn)登陸的兩種方法。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考2016-05-05
JavaScript詳解類數(shù)組與可迭代對象的實現(xiàn)原理
這篇文章主要介紹了JavaScript詳解類數(shù)組與可迭代對象的實現(xiàn)原理,ES6中引入了迭代器與可迭代對象的概念,并且提供了對可迭代對象的相關(guān)支持,如for...of循環(huán),Map(iterable)構(gòu)造器,展開語法...等。讓我們對數(shù)組外的數(shù)據(jù)集合的遍歷操作也得到極大簡化2022-06-06
JS生態(tài)系統(tǒng)加速一次一庫PostCSS SVGO的重構(gòu)源碼和性能優(yōu)化探索
這篇文章主要介紹了JS生態(tài)系統(tǒng)加速一次一庫PostCSS SVGO的重構(gòu)源碼和性能優(yōu)化探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01

