談談我對JavaScript中typeof和instanceof的深入理解_javascript技巧

來源:互聯網
上載者:User

這次主要說說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”

再看看具體的執行個體:

// Numberstypeof 37 === 'number';typeof 3.14 === 'number';typeof Math.LN2 === 'number';typeof Infinity === 'number';typeof NaN === 'number'; // 儘管NaN是"Not-A-Number"的縮寫,意思是"不是一個數字"typeof Number(1) === 'number'; // 不要這樣使用!// Stringstypeof "" === 'string';typeof "bla" === 'string';typeof (typeof 1) === 'string'; // typeof返回的肯定是一個字串typeof String("abc") === 'string'; // 不要這樣使用!// Booleanstypeof true === 'boolean';typeof false === 'boolean';typeof Boolean(true) === 'boolean'; // 不要這樣使用!// Symbolstypeof Symbol() === 'symbol';typeof Symbol('foo') === 'symbol';typeof Symbol.iterator === 'symbol';// Undefinedtypeof undefined === 'undefined';typeof blabla === 'undefined'; // 一個未定義的變數,或者一個定義了卻未賦初值的變數// Objectstypeof {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.prototypeo instanceof C; // false,因為 D.prototype不在o的原型鏈上o instanceof D; o instanceof Object; // true,因為Object.prototype.isPrototypeOf(o)返回trueC.prototype instanceof Object // true,同上C.prototype = {};var o2 = new C();o2 instanceof C; // trueo instanceof C; // false,C.prototype指向了一個Null 物件,這個Null 物件不在o的原型鏈上.D.prototype = new C(); // 繼承var o3 = new D();o3 instanceof D; // trueo3 instanceof C; // true

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

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

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.