欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript檢測原始值、引用值、屬性

 更新時(shí)間:2016年06月20日 17:23:11   投稿:mrr  
這篇文章主要介紹了JavaScript檢測原始值、引用值、屬性的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下

在 JavaScript 中,我們常常會(huì)看到這樣的代碼:變量與 null 的比較(這種用法很有問題),用來判斷變量是否被賦予了一個(gè)合理的值。比如:

var Controller = {
process: function(items) {
if (items !== null) { // 不好的寫法
items.sort();
items.forEach(function(item) {
// 執(zhí)行一些邏輯
});
}
}
}

在這段代碼中, process() 方法顯然希望 items 是一個(gè)數(shù)組,因?yàn)槲覀兛吹?items 擁有 sort() 和 forEach() 。這段代碼的意圖非常明顯:如果參數(shù) items 不是一個(gè)組數(shù),則停止接下來的操作。這種寫法的問題在于,和 null 的比較并不能真正避免錯(cuò)誤的發(fā)生。 items 的值可以是1,也可以是是字符串,甚至可以是任意對(duì)象。這些值都和 null 不相等,進(jìn)而會(huì)導(dǎo)致 process() 方法一旦執(zhí)行到 sort() 時(shí)就會(huì)出錯(cuò)。

僅僅和 null 比較并不能提供足夠的信息來判斷后續(xù)代碼的執(zhí)行是否真的安全。好在 JavaScript 為我們提供了很多種方法來檢測變量的真實(shí)值。

檢測原始值

在 JavaScript 中有5種原始類型(也稱為簡單數(shù)據(jù)類型): String 、 Number 、 Boolean 、 Undefined 和 Null 。如果你希望一個(gè)值是 String 、 Number 、 Boolean 或 Undefined ,最佳選擇是使用 typeof 運(yùn)算符,它會(huì)返回一個(gè)表示類型的字符串。

對(duì)于字符串, typeof 返回 "string" 。

對(duì)于數(shù)字, typeof 返回 "number" 。

對(duì)于布爾值, typeof 返回 "boolean" 。

對(duì)于undefined, typeof 返回 "undefined" 。

typeof 的基本語法是: typeof variable ,你還可以這樣用: typeof(variable) ,盡管這是合法的 JavaScript 語法,這種用法讓 typeof 看起來像一個(gè)函數(shù)而非運(yùn)算符。鑒于此,我們更推薦無括號(hào)的寫法。

使用 typeof 來檢測這4種原始類型是非常安全的做法。來看下面這些例子。

// 檢測"String"
if (typeof name === "string") {
anotherName = name.substring(3);
}
// 檢測"Number"
if (typeof count === "number") {
updateCount(count);
}
// 檢測"Boolean"
if (typeof found === "boolean" && found) {
message("Found!");
}
// 檢測"Undefined"
if (typeof MyApp === "undefined") {
MyApp = {
// 其他代碼
};
}

typeof 運(yùn)算符的獨(dú)特之處在于,將其用于一個(gè)未聲明的變量也不會(huì)報(bào)錯(cuò)。未定義的變量和值為 undefined 的變量通過 typeof 都將返回 "undefined" 。

最后一個(gè)原始類型 null ,通過 typeof 將返回 "object" ,這看上去很怪異,被認(rèn)為是標(biāo)準(zhǔn)規(guī)范的嚴(yán)重 bug,因此在編程時(shí)要 杜絕使用 typeof 來檢測 null 的類型 。

console.log(typeof null); // "object"

簡單地和 null 進(jìn)行比較通常不會(huì)包含足夠的信息以判斷值的類型是否合法,所以 null 一般不應(yīng)用于檢測語句。

但有一個(gè)例外,如果所期望的值真的是 null ,則可以直接和 null 進(jìn)行比較。例如:

// 如果你需要檢測 null,則使用這種方法
var element = document.getElementById("my-div");
if (element !== null) {
element.className = "found";
}

如果 DOM 元素不存在,則通過 document.getElementById() 得到的值為 null 。這個(gè)方法要么返回一個(gè)節(jié)點(diǎn),要么返回 null 。由于這時(shí) null 是可預(yù)見的一種輸出,則可以用恒等運(yùn)算符 === 或非恒等運(yùn)算符 !== 來檢測返回結(jié)果。

typeof 運(yùn)算符的返回值除了上述提到的 string 、 number 、 boolean 、 undefined 和 object 之外,還有 function 。從技術(shù)的角度來講,函數(shù)在 JavaScript 中也是對(duì)象,不是一種數(shù)據(jù)類型。然而,函數(shù)也確實(shí)有一些特殊的屬性,因此通過 typeof 運(yùn)算符來區(qū)分函數(shù)和其他對(duì)象是有必要的。這一特性將在后面 檢測函數(shù) 中用到。

檢測引用值

在 JavaScript 中除了原始值之外的都是引用值(也稱為對(duì)象),常用的引用類型有: Object 、 Array 、 Date 和 RegExp ,這些引用類型都是 JavaScript 的內(nèi)置對(duì)象。 typeof 運(yùn)算符在判斷這些引用類型時(shí)全都返回 "object" 。

console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof new Date()); // "object"
console.log(typeof new RegExp()); // "object"

檢測某個(gè)引用值類型的最好方法是使用 instanceof 運(yùn)算符, instanceof 的基本語法是:

value instanceof constructor
// 檢測日期
if (value instanceof Date) {
console.log(value.getFullYear);
}
// 檢測 Error
if (value instanceof Error) {
throw value;
}
// 檢測正則表達(dá)式
if (value instanceof RegExp) {
if (value.test(anotherValue)) {
console.log("Matches");
}
}

instanceof 的一個(gè)有意思的特性是它不僅檢測構(gòu)造這個(gè)對(duì)象的構(gòu)造器,還檢測原型鏈。原型鏈包含了很多信息,包括定義對(duì)象所采用的繼承模式。比如,默認(rèn)情況下,每個(gè)對(duì)象都繼承自 Object ,因此每個(gè)對(duì)象的 value instanceof Object 都會(huì)返回 ture 。比如:

var now = new Date();
console.log(now instanceof Object); // ture
console.log(now instanceof Date); // ture
instanceof 運(yùn)算符也可以檢測自定義的類型,比如:
function Person(name){
this.name = name;
}
var me = new Person("Nicholas");
console.log(me instanceof Object); // ture
console.log(me instanceof Person); // ture

這段示例代碼中創(chuàng)建了 Person 類型。變量 me 是 Person 的實(shí)例,因此 me instanceof Person 是 true 。上文也提到,所有的對(duì)象都被認(rèn)為是 Object 的實(shí)例,因此 me instanceof Object 也是 ture 。

在 JavaScript 中檢測 內(nèi)置類型 和 自定義類型 時(shí),最好的做法就是使用 instanceof 運(yùn)算符,這也是唯一的方法。

但有一個(gè)嚴(yán)重的限制,假設(shè)兩個(gè)瀏覽器幀(frame)里都有構(gòu)造函數(shù) Person ,幀A中的 Person 實(shí)例 frameAPersonInstance 傳入到幀B中,則會(huì)有如下結(jié)果:

console.log(frameAPersonInstance instanceof frameAPerson) // ture
console.log(frameAPersonInstance instanceof frameBPerson) // false
盡管兩個(gè) Person 的定義是完全一樣的,但在不同幀(frame)里,他們被認(rèn)為是不同類型。有兩個(gè)非常重要的內(nèi)置類型也有這個(gè)問題: Array 和 Function ,所以檢測它們一般不使用 instanceof 。

檢測函數(shù)

從技術(shù)上講,JavaScript 中的函數(shù)是引用類型,同樣存在 Function 構(gòu)造函數(shù),每個(gè)函數(shù)都是其實(shí)例,比如:

function myFunc() {}
// 不好的寫法
console.log(myFunc instanceof Function); // true

然而,這個(gè)方法亦不能跨幀(frame)使用,因?yàn)槊總€(gè)幀都有各自的 Function 構(gòu)造函數(shù),好在 typeof 運(yùn)算符也是可以用于函數(shù)的,返回 "function" 。

function myFunc() {}
// 好的寫法
console.log(typeof myFunc === "function"); // true

檢測函數(shù)最好的方法是使用 typeof ,因?yàn)樗梢钥鐜╢rame)使用。

用 typeof 來檢測函數(shù)有一個(gè)限制。在 IE 8 和更早版本的 IE 瀏覽器中,使用 typeof 來檢測 DOM 節(jié)點(diǎn)中的函數(shù)都返回 "object" 而不是 "function" 。比如:

// IE8 及更早版本的IE
console.log(typeof document.createElement); // "object"
console.log(typeof document.getElementById); // "object"
console.log(typeof document.getElementByTagName); // "object"

之所以出現(xiàn)這種怪異的現(xiàn)象是因?yàn)闉g覽器對(duì) DOM 的實(shí)現(xiàn)有差異。簡言之,這些早版本的 IE 并沒有將 DOM 實(shí)現(xiàn)為內(nèi)置的 JavaScript 方法,導(dǎo)致內(nèi)置 typeof 運(yùn)算符將這些函數(shù)識(shí)別為對(duì)象。因?yàn)?DOM 是有明確定義的,了解到對(duì)象成員如果存在則意味著它是一個(gè)方法,開發(fā)者往往通過 in 運(yùn)算符來檢測 DOM 的方法,比如:

// 檢測 DOM 方法
if ("querySelectorAll" in document) {
var images = document.querySelectorAll("img");
}

這段代碼檢查 querySelectorAll 是否定義在 document 中,如果是,則使用這個(gè)方法。盡管不是最理想的方法,如果想在 IE 8 及更早瀏覽器中檢測 DOM 方法是否存在,這是最安全的做法。在其他所有的情形中, typeof 運(yùn)算符是檢測 JavaScript 函數(shù)的最佳選擇。

檢測數(shù)組

JavaScript 中最古老的跨域問題之一就是在幀(frame)之間來回傳遞數(shù)組。開發(fā)者很快發(fā)現(xiàn) instanceof Array 在此場景中不能返回正確的結(jié)果。正如上文提到的,每個(gè)幀都有各自的 Array 構(gòu)造函數(shù),因此一個(gè)幀中的實(shí)例在另外一個(gè)幀里不會(huì)被識(shí)別。

關(guān)于如何在 JavaScript 中檢測數(shù)組類型已經(jīng)有狠多研究了,最終 Kangax 給出了一種優(yōu)雅的解決方案:

function isArray(value) {
return Object.prototype.toString.call(value) === "[object Array]";
}

Kangax 發(fā)現(xiàn)調(diào)用某個(gè)值的內(nèi)置 toString() 方法在所有瀏覽器中都會(huì)返回標(biāo)準(zhǔn)的字符串結(jié)果。對(duì)于數(shù)組來說,返回的字符串為 "[object Array]" ,也不用考慮數(shù)組實(shí)例實(shí)在哪個(gè)幀(frame)中被構(gòu)造出來的。這種方法在識(shí)別內(nèi)置對(duì)象時(shí)往往十分有用,但對(duì)于自定義對(duì)象請(qǐng)不要用這種方法。

ECMAScript5 將 Array.isArray() 正式引入 JavaScript。唯一的目的就是準(zhǔn)確地檢測一個(gè)值是否為數(shù)組。同 Kangax 的函數(shù)一樣, Array.isArray() 也可以檢測跨幀(frame)傳遞的值,因此很多 JavaScript 類庫目前都類似地實(shí)現(xiàn)了這個(gè)方法。

function isArray(value) {
if (typeof Array.isArray === "function") {
return Array.isArray(value);
} else {
return Object.prototype.toString.call(value) === "[object Array]";
}
}

IE 9+、FireFox 4+、Safari 5+、Opera 10.5+、Chrome 都實(shí)現(xiàn)了 Array.isArray() 方法。

檢測屬性

另外一種用到 null (以及 undefined )的場景是當(dāng)檢測一個(gè)屬性是否在對(duì)象中存在時(shí),比如:

// 不好的寫法:檢測假值
if (object[propertyName]) {
// 一些代碼
}
// 不好的寫法:和null相比較
if (object[propertyName] != null) {
// 一些代碼
}
// 不好的寫法:和undefined相比較
if (object[propertyName] != undefined) {
// 一些代碼
}

上面這段代碼里的每個(gè)判斷,實(shí)際上是通過給定的名字來檢查屬性的值,而并非判斷給定的名字所指的屬性是否存在。在第一個(gè)判斷中,當(dāng)屬性值為假值時(shí)結(jié)果會(huì)出錯(cuò),比如: 0 、 ""(空字符串) 、 false 、 null 和 undefined ,畢竟這些都是屬性的合法值。

判斷屬性是否存在的最好的方法是使用 in 運(yùn)算符。 in 運(yùn)算符僅僅會(huì)簡單地判斷屬性是否存在,而不去讀屬性的值,如果實(shí)例對(duì)象的屬性存在、或者繼承自對(duì)象的原型, in 運(yùn)算符都會(huì)返回 true 。比如:

var object = {
count: 0,
related: null
};
// 好的寫法
if ("count" in object) {
// 這里的代碼會(huì)執(zhí)行
}
// 不好的寫法:檢測假值
if (object["count"]) {
// 這里的代碼不會(huì)執(zhí)行
}
// 好的寫法
if ("related" in object) {
// 這里的代碼會(huì)執(zhí)行
}
// 不好的寫法,檢測是否為
if (object["related"] != null) {
// 這里的代碼不會(huì)執(zhí)行
}

如果你只想檢查實(shí)例對(duì)象的某個(gè)屬性是否存在,則使用 hasOwnProperty() 方法。所有繼承自 Object 的 JavaScript 對(duì)象都有這個(gè)方法,如果實(shí)例中存在這個(gè)屬性則返回 true (如果這個(gè)屬性只存在于原型里,則返回 false )。需要注意的是,在 IE 8 以及更早版本的 IE 中,DOM 對(duì)象并非繼承自 Object,因此也不包含這個(gè)方法。也就是說,你在調(diào)用 DOM 對(duì)象的 hasOwnProperty() 方法之前應(yīng)當(dāng)先檢測其是否存在。

// 對(duì)于所有非 DOM 對(duì)象來說,這是好的寫法
if (object.hasOwnProperty("related")) {
// 執(zhí)行這里的代碼會(huì)
}
// 如果你不確定是否為 DOM 對(duì)象,則這樣來寫
if ("hasOwnProperty" in object && object.hasOwnProperty("related")) {
// 執(zhí)行這里的代碼會(huì)
}

因?yàn)榇嬖?IE 8 以及更早版本的 IE 的情形,在判斷實(shí)例對(duì)象的屬性是否存在時(shí),我更傾向于使用 in 運(yùn)算符,只有在需要判斷實(shí)例屬性時(shí)才會(huì)用到 hasOwnProperty() 。

不管你什么時(shí)候需要檢測屬性的存在性,請(qǐng)使用 in 運(yùn)算符或者 hasOwnProperty() 。這樣做可以避免很多 bug。

以上所述是小編給大家介紹的JavaScript檢測原始值、引用值、屬性,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

最新評(píng)論