首頁 > web前端 > js教程 > 在JavaScript中typeof的用途介紹_基礎知識

在JavaScript中typeof的用途介紹_基礎知識

WBOY
發布: 2016-05-16 17:37:31
原創
1031 人瀏覽過

JavaScript 中的 typeof 其實非常複雜,它可以用來做很多事情,但同時也有很多怪異的表現。

本文列舉出了它的多個用法,而且也指出了存在的問題以及解決方案。

閱讀本文的前提是,你現在應該已經知道原始值和物件值的差別了。

檢查一個變數是否存在,是否有值
typeof在兩種情況下會回傳 "undefined":

1.變數沒有被宣告

2.變數的值是 undefined

例如:

複製程式碼 程式碼如下:

type type undefined"
true

> var declaredVariable;
> typeof declaredVariable
'undefined'

> typeof undefined
'undefined'

還有其他辦法可以偵測某個值是否是 undefined:

複製程式碼 程式碼如下:

> var value = undefined; == undefined
true

但這種方法如果使用在一個未宣告的變數上的時候,就會拋出異常,因為只有 typeof 才可以正常檢測未宣告的變數的同時還不報錯:

複製程式碼 程式碼如下:
> undeclaredVariable === un> is not defined


注意:未初始化的變量,沒有被傳入參數的形參,不存在的屬性,都不會出現上面的問題,因為它們總是可訪問的,值總是 undefined:

複製程式碼 程式碼如下:
> varl declaredVable;


> var =claredVable; undefined
true

> (function (x) { return x === undefined }())
true

> ({}).foo === undefined
true

譯者註:因此,如果想偵測一個可能沒有被宣告的全域變數是否存在,也可以使用if(window.maybeUndeclaredVariable){}。

問題:typeof 在完成這樣的任務時顯得很繁雜.

解決方法:這樣的操作不是很常見,所以有人覺的沒必要再找更好的解決辦法了。 不過也許有人會提出一個專門的操作符:

複製程式碼 程式碼如下:

> defined undeclaredV​​eable> var declaredVariable;> defined declaredVariable

false


或者,也許有人還需要一個偵測變數是否被宣告的運算子:

複製程式碼 程式碼如下:
> declaredund
> var declaredVariable;
> declared declaredVariable
true



譯者註:在 perl 裡,上面的 defined 操作符相當於 defined(),上面的 declared 操作符相當於 exists()。

判斷一個值不等於undefined 也不等於null

問題:如果你想檢測一個值是否被定義過(值不是undefined 也不是null),那麼你就遇到了typeof 最有名的一個怪異表現(被認為是一個bug):typeof null 回傳了"object":


複製程式碼

程式碼如下:> typeof null 'object'

譯者註:這只能說是最初的 JavaScript 實作的 bug,而現在標準就是這樣規範的。 V8 曾經修正並實現過 typeof null === "null",但最終證明不可行。 http://wiki.ecmascript.org/doku.php?id=harmony:typeof_null。

(翻譯:typeof 在操作null 時會回傳"object",這是JavaScript 語言本身的bug。不幸的是,這個bug 永遠不可能被修復了,因為太多已有的程式碼已經依賴了這樣的表現。

解決方法:不要使用 typeof 來做這項任務,用下面這樣的函數來代替:

複製程式碼 程式碼如下:
function isDefined(x) {
f == null && x !== undefined;
}

另一個可能性是引入一個 “預設值運算子”,在 myValue 未定義的情況下,下面的表達式會傳回 defaultValue:

複製程式碼 程式碼如下:
myValue ?? def >
上面的表達式等價於:

複製程式碼

程式碼如下:(myValue !== undefined &==& mydefined &== ) ? myValue : defaultValue

又或:

複製程式碼

程式碼如下:myValue ??= defaultValue
myValue ??= defaultValue

myValue ??= defaultValue

myValue ??= defaultValue

myValue ??= defaultValuemyValue ??= defaultValue
myValue ?? 🎜>
其實是下面這句話的簡化:

複製程式碼

程式碼如下:myValue = my ? defaultd 當你存取一個巢狀的屬性時,例如 bar,你或許會需要這個運算子的幫助:


複製程式碼

程式碼如下:

obj.foo.barobj.foo.bar

如果 obj 或 obj.foo 是未定義的,上面的表達式會拋出異常。 一個運算子 .?? 可以讓上面的表達式在遍歷一層一層的屬性時,傳回第一個遇到的值為 undefined 或 null 的屬性:

複製程式碼 程式碼如下:
obj.??foo.?bar


上面的表達式等價於:

複製程式碼

程式碼如下:

(obj === undefined || || null) ? obj    : (obj.foo === undefined || obj.foo === null) ? obj.foo        : obj.foo.bar區分物件值與原始值
下面的函數用來偵測 x 是否為物件值:




複製程式碼

程式碼如下:

function isObjectx) {


問題:上面的偵測比較複雜,是因為 typeof 把函數和物件看成是不同的型,而且 typeof null 回傳 "object".

解決方法:下面的方法也常用於偵測物件值:
複製程式碼 程式碼如下:function isObject2(x) { == Object(x);}

警告:你也許認為這裡可以使用 instanceof Object 來檢測,但是 instanceof 是透過使用使用一個物件的原型來判斷實例關係的,那麼沒有原型的物件怎麼辦呢:

複製程式碼 程式碼如下:

> var obj = Object.create(null); 🎜>> Object.getPrototypeOf(obj)
null

obj 確實是一個對象,但它不是任何值的實例:

複製程式碼 程式碼如下:
> typeof obj


> typeof obj
'object' > obj instanceof Object
false

在實際中,你可能很少遇到這樣的對象,但它的確存在,而且有它的用途。

譯者註:Object.prototype 就是唯一的內建的,沒有原型的物件。

程式碼如下:


>Object.getPrototypeOf(sObject.prototype. null
>typeof Object.prototype
'object'
>Object.prototype instanceof Object
false

原始值的類型是什麼?
typeof 是最好的用來查看某個原始值的類型的方式。

複製程式碼 程式碼如下:

> typeof "abc"


> typeof "abc"
'string'
> typeof undefined'undefined'

問題:你必須知道 typeof null 的怪異表現。 複製程式碼

程式碼如下:

> typeof null  // 要小心當! object'

解決方法:下面的函數可以修復這個問題(只針對這個用例)。

複製程式碼
程式碼如下:


function getPrimitiveTypeName(x) {

function getPrimitiveTypeName(x) { typeof x;
    switch(typeName) {
        case "undefined":
           case "string":
            return typeName;
        case "object":
            if (x === null) {        default: // 前面的判斷都未通過
           ("參數不是原始值: " x);
    }
}

更好的解決方法:實作一個函數 getTypeName(),除了可以傳回原始值的的類型,還可以傳回物件值的內部 [[Class]] 屬性。 這裡講如何實現這個函數(譯者註:jQuery 中的 $.type 就是這樣的實作)

某個值是否是函數
typeof 可以用來偵測一個值是否是函數。

複製程式碼 程式碼如下:
> typeof function () {}
'function '
> typeof Object.prototype.toString
'function'

原則上說,instanceof Function 也可以進行這種需求的偵測。 乍一看,似乎寫法更優雅。 但是,瀏覽器有一個怪癖:每個框架和視窗都有它自己的全域變數。 因此,如果你將某個框架中的物件傳到另一個框架中,instanceof 就無法正常運作了,因為這兩個框架有著不同的建構子。 這就是為什麼 ECMAScript5 中會有Array.isArray() 方法的原因。 如果有一個能夠跨框架的,用於檢查一個物件是否是給定的建構函數的實例的方法的話,那會很好。 上述的 getTypeName() 是一個可用的變通方法,但也許還有一個更根本的解。

綜述
下面提到的,應該是目前 JavaScript 中最迫切需要的,可以代替一些 typeof 目前職責的功能特性:

•isDefined() (例如 Object.isDefined()): 可以當作一個函數或一個運算子

•isObject()

•getTypeName()

•能夠跨框架的,偵測一個物件是否是指定的建構子的實例的機制

檢查某個變數是否已經被宣告這樣的需求,可能沒那麼必要有自己的運算子。

 

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板