DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> 談談我對JavaScript中typeof和instanceof的深入理解
談談我對JavaScript中typeof和instanceof的深入理解
編輯:關於JavaScript     

這次主要說說javascript的類型判斷函數typeof和判斷構造函數原型instanceof的用法和注意的地方。

typeof

先來說說typeof吧。首先需要注意的是,typeof方法返回一個字符串,來表示數據的類型。

typeof 是一個一元運算,放在一個運算數之前,運算數可以是任意類型。

它返回值是一個字符串,該字符串說明運算數的類型。typeof 一般只能返回如下幾個結果:
number,boolean,string,function,object,undefined。我們可以使用 typeof 來獲取一個變量是否存在,如 if(typeof a!="undefined"){alert("ok")},而不要去使用 if(a) 因為如果 a 不存在(未聲明)則會出錯,對於 Array,Null 等特殊對象使用 typeof 一律返回 object,這正是 typeof 的局限性。

語法講解

我們先看看各個數據類型對應typeof的值:

數據類型 Type Undefined “undefined” Null “object” 布爾值 “boolean” 數值 “number” 字符串 “string” Symbol (ECMAScript 6 新增) “symbol” 宿主對象(JS環境提供的,比如浏覽器) Implementation-dependent 函數對象 “function” 任何其他對象 “object”

再看看具體的實例:

// Numbers
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // 盡管NaN是"Not-A-Number"的縮寫,意思是"不是一個數字"
typeof Number(1) === 'number'; // 不要這樣使用!
// Strings
typeof "" === 'string';
typeof "bla" === 'string';
typeof (typeof 1) === 'string'; // typeof返回的肯定是一個字符串
typeof String("abc") === 'string'; // 不要這樣使用!
// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(true) === 'boolean'; // 不要這樣使用!
// Symbols
typeof Symbol() === 'symbol';
typeof Symbol('foo') === 'symbol';
typeof Symbol.iterator === 'symbol';
// Undefined
typeof undefined === 'undefined';
typeof blabla === 'undefined'; // 一個未定義的變量,或者一個定義了卻未賦初值的變量
// Objects
typeof {a:1} === 'object';
// 使用Array.isArray或者Object.prototype.toString.call方法可以從基本的對象中區分出數組類型
typeof [1, 2, 4] === 'object';
typeof new Date() === 'object';
// 下面的容易令人迷惑,不要這樣使用!
typeof new Boolean(true) === 'object';
typeof new Number(1) ==== 'object';
typeof new String("abc") === 'object';
// 函數
typeof function(){} === 'function';
typeof Math.sin === 'function';

我們會發現一個問題,就是typeof來判斷數據類型其實並不准確。比如數組、正則、日期、對象的typeof返回值都是object,這就會造成一些誤差。

所以在typeof判斷類型的基礎上,我們還需要利用Object.prototype.toString方法來進一步判斷數據類型。

我們來看看在相同數據類型的情況下,toString方法和typeof方法返回值的區別:

數據 toString typeof “foo” String string new String(“foo”) String object new Number(1.2) Number object true Boolean boolean new Boolean(true) Boolean object new Date() Date object new Error() Error object new Array(1, 2, 3) Array object /abc/g RegExp object new RegExp(“meow”) RegExp object

可以看到利用toString方法可以正確區分出Array、Error、RegExp、Date等類型。

所以我們一般通過該方法來進行數據類型的驗證

真題檢測

但是既然今天說到了typeof,那這裡就列出幾道題目,來看看自己是否真正掌握了typeof的用法。

第一題:

var y = 1, x = y = typeof x;
x;

第二題:

(function f(f){
return typeof f();
})(function(){ return 1; });

第三題:

var foo = {
bar: function() { return this.baz; },
baz: 1
};
(function(){
return typeof arguments[0]();
})(foo.bar);

第四題:

var foo = {
bar: function(){ return this.baz; },
baz: 1
}
typeof (f = foo.bar)();

第五題:

var f = (function f(){ return "1"; }, function g(){ return 2; })();
typeof f;

第六題:

var x = 1;
if (function f(){}) {
x += typeof f;
}
x;

第七題:

(function(foo){
return typeof foo.bar;
})({ foo: { bar: 1 } });

下面公布答案了,這七題的答案分別是:

"undefined","number","undefined","undefined","number","1undefined","undefined"

做對了幾道呢?是不是很大的困惑呢?這幾題雖然都有typeof,但是考察了很多javascript的基礎噢。下面我們來一一詳解。

第一題:

var y = 1, x = y = typeof x;
x;//"undefined"

表達式是從右往左的,x由於變量提升,類型不是null,而是undefined,所以x=y=”undefined”。

變量提升我在這篇文章中提到過,可以看看。

第二題:

(function f(f){
return typeof f();//"number"
})(function(){ return 1; });

傳入的參數為f也就是function(){ return 1; }這個函數。通過f()執行後,得到結果1,所以typeof 1返回”number”。這道題很簡單,主要是區分f和f()。

第三題:

var foo = {
bar: function() { return this.baz; },
baz: 1
};
(function(){
return typeof arguments[0]();//"undefined"
})(foo.bar);

這一題考察的是this的指向。this永遠指向函數執行時的上下文,而不是定義時的(ES6的箭頭函數不算)。當arguments執行時,this已經指向了window對象。所以是”undefined”。對this執行不熟悉的同學可以看看這篇文章:深入理解this,對剛剛提到的箭頭函數感興趣的同學可以看看初步探究ES6之箭頭函數。

第四題:

var foo = {
bar: function(){ return this.baz; },
baz: 1
}
typeof (f = foo.bar)();//undefined

如果上面那一題做對了,那麼這一題也應該不會錯,同樣是this的指向問題。

第五題:

var f = (function f(){ return "1"; }, function g(){ return 2; })();
typeof f;//"number"

這一題比較容易錯,因為我在遇到這道題之前也從來沒有遇到過javascript的分組選擇符。什麼叫做分組選擇符呢?舉一個例子就會明白了:

var a = (1,2,3);
document.write(a);//3,會以最後一個為准

所以上面的題目會返回2,typeof 2當然是”number”啦。

第六題:

var x = 1;
if (function f(){}) {
x += typeof f;
}
x;//"1undefined"

這是一個javascript語言規范上的問題,在條件判斷中加入函數聲明。這個聲明語句本身沒有錯,也會返回true,但是javascript引擎在搜索的時候卻找不到該函數。所以結果為”1undefined”。

第七題:

(function(foo){
return typeof foo.bar;
})({ foo: { bar: 1 } });

這題其實是一個考察心細程度的題目。形參的foo指向的是{ foo: { bar: 1 } }這個整體。相信這麼說就明白了。

好啦。上面的題目都是很好的資源噢。

instanceof

接下來該說說instanceof方法了。instanceof運算符可以用來判斷某個構造函數的prototype屬性是否存在於另外一個要檢測對象的原型鏈上。

instanceof 用於判斷一個變量是否某個對象的實例,如 var a=new Array();alert(a instanceof Array); 會返回 true,同時 alert(a instanceof Object) 也會返回 true;這是因為 Array 是 object 的子類。再如:function test(){};var a=new test();alert(a instanceof test) 會返回

談到 instanceof 我們要多插入一個問題,就是 function 的 arguments,我們大家也許都認為 arguments 是一個 Array,但如果使用 instaceof 去測試會發現 arguments 不是一個 Array 對象,盡管看起來很像。

如果對原型不太了解,可以看看深入理解原型。

下面我們看看instanceof的實例:

// 定義構造函數
function C(){} 
function D(){} 
var o = new C();
// true,因為 Object.getPrototypeOf(o) === C.prototype
o instanceof C; 
// false,因為 D.prototype不在o的原型鏈上
o instanceof D; 
o instanceof Object; // true,因為Object.prototype.isPrototypeOf(o)返回true
C.prototype instanceof Object // true,同上
C.prototype = {};
var o2 = new C();
o2 instanceof C; // true
o instanceof C; // false,C.prototype指向了一個空對象,這個空對象不在o的原型鏈上.
D.prototype = new C(); // 繼承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true

但是這裡我們需要注意一個問題:

function f(){ return f; }
document.write(new f() instanceof f);//false
function g(){}
document.write(new g() instanceof g);//true

第一個為什麼返回false呢?因為構造函數的原型被覆蓋了,我們可以看看new f和new g的區別:

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved