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

Array, Array Constructor, for in loop, typeof, instanceOf

 更新時間:2011年09月13日 22:08:48   作者:  
雖然在 JavaScript 中數(shù)組是是對象,但是沒有好的理由去使用 `for in` 循環(huán) 遍歷數(shù)組。相反,有一些好的理由不去使用 for in 遍歷數(shù)組。
注意: JavaScript 中數(shù)組不是 關(guān)聯(lián)數(shù)組。 JavaScript 中只有對象 來管理鍵值的對應關(guān)系。但是關(guān)聯(lián)數(shù)組是保持順序的,而對象不是。

由于 for in 循環(huán)會枚舉原型鏈上的所有屬性,唯一過濾這些屬性的方式是使用 `hasOwnProperty` 函數(shù),因此會比普通的 for 循環(huán)慢上好多倍。

遍歷(Iteration)
為了達到遍歷數(shù)組的最佳性能,推薦使用經(jīng)典的 for 循環(huán)。
復制代碼 代碼如下:

var list = [1, 2, 3, 4, 5, ...... 100000000];
for(var i = 0, l = list.length; i < l; i++) {
console.log(list[i]);
}

上面代碼有一個處理,就是通過 l = list.length 來緩存數(shù)組的長度。

雖然 length 是數(shù)組的一個屬性,但是在每次循環(huán)中訪問它還是有性能開銷。 可能最新的 JavaScript 引擎在這點上做了優(yōu)化,但是我們沒法保證自己的代碼是否運行在這些最近的引擎之上。

實際上,不使用緩存數(shù)組長度的方式比緩存版本要慢很多。

`length` 屬性(The `length` property)
length 屬性的 getter 方式會簡單的返回數(shù)組的長度,而 setter 方式會截斷數(shù)組。
復制代碼 代碼如下:

var foo = [1, 2, 3, 4, 5, 6];
foo.length = 3;
foo; // [1, 2, 3]

foo.length = 6;
foo; // [1, 2, 3]

譯者注:在 Firebug 中查看此時 foo 的值是: [1, 2, 3, undefined, undefined, undefined] 但是這個結(jié)果并不準確,如果你在 Chrome 的控制臺查看 foo 的結(jié)果,你會發(fā)現(xiàn)是這樣的: [1, 2, 3] 因為在 JavaScript 中 undefined 是一個變量,注意是變量不是關(guān)鍵字,因此上面兩個結(jié)果的意義是完全不相同的。

// 譯者注:為了驗證,我們來執(zhí)行下面代碼,看序號 5 是否存在于 foo 中。
5 in foo; // 不管在 Firebug 或者 Chrome 都返回 false
foo[5] = undefined;
5 in foo; // 不管在 Firebug 或者 Chrome 都返回 true
為 length 設置一個更小的值會截斷數(shù)組,但是增大 length 屬性值不會對數(shù)組產(chǎn)生影響。

結(jié)論(In conclusion)
為了更好的性能,推薦使用普通的 for 循環(huán)并緩存數(shù)組的 length 屬性。使用 for in 遍歷數(shù)組被認為是不好的代碼習慣并傾向于產(chǎn)生錯誤和導致性能問題。

Array 構(gòu)造函數(shù)
由于 Array 的構(gòu)造函數(shù)在如何處理參數(shù)時有點模棱兩可,因此總是推薦使用數(shù)組的字面語法 - [] - 來創(chuàng)建數(shù)組。

[1, 2, 3]; // 結(jié)果: [1, 2, 3]
new Array(1, 2, 3); // 結(jié)果: [1, 2, 3]

[3]; // 結(jié)果: [3]
new Array(3); // 結(jié)果: []
new Array('3') // 結(jié)果: ['3']
譯者注:這里的模棱兩可指的是數(shù)組的兩種構(gòu)造函數(shù)語法 var arr1 = new Array(arrayLength); var arr2 = new Array(element0, element1, ..., elementN);

// 譯者注:因此下面的代碼將會使人很迷惑
new Array(3, 4, 5); // 結(jié)果: [3, 4, 5]
new Array(3) // 結(jié)果: [],此數(shù)組長度為 3
由于只有一個參數(shù)傳遞到構(gòu)造函數(shù)中(譯者注:指的是 new Array(3); 這種調(diào)用方式),并且這個參數(shù)是數(shù)字,構(gòu)造函數(shù)會返回一個 length 屬性被設置為此參數(shù)的空數(shù)組。需要特別注意的是,此時只有 length 屬性被設置,真正的數(shù)組并沒有生成。譯者注:在 Firebug 中,你會看到 [undefined, undefined, undefined],這其實是不對的。在上一節(jié)有詳細的分析。

var arr = new Array(3);
arr[1]; // undefined
1 in arr; // false, 數(shù)組還沒有生成
這種優(yōu)先于設置數(shù)組長度屬性的做法只在少數(shù)幾種情況下有用,比如需要循環(huán)字符串,可以避免 for 循環(huán)的麻煩。

new Array(count + 1).join(stringToRepeat);
// 譯者注:new Array(3).join('#') 將會返回 "##"
結(jié)論(In conclusion)
應該盡量避免使用數(shù)組構(gòu)造函數(shù)創(chuàng)建新數(shù)組。推薦使用數(shù)組的字面語法。它們更加短小和簡潔,因此增加了代碼的可讀性。

for in 循環(huán)
和 in 操作符一樣,for in 循環(huán)同樣在查找對象屬性時遍歷原型鏈上的所有屬性。

注意: for in 循環(huán)不會遍歷那些 enumerable 設置為 false 的屬性;比如數(shù)組的 length 屬性。
復制代碼 代碼如下:

// 修改 Object.prototype
Object.prototype.bar = 1;

var foo = {moo: 2};
for(var i in foo) {
console.log(i); // 輸出兩個屬性:bar 和 moo
}

由于不可能改變 for in 自身的行為,因此有必要過濾出那些不希望出現(xiàn)在循環(huán)體中的屬性,這可以通過 Object.prototype 原型上的 `hasOwnProperty` 函數(shù)來完成。

注意: 由于 for in 總是要遍歷整個原型鏈,因此如果一個對象的繼承層次太深的話會影響性能。

使用 `hasOwnProperty` 過濾(Using `hasOwnProperty` for filtering)
復制代碼 代碼如下:

// foo 變量是上例中的
for(var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i);
}
}

這個版本的代碼是唯一正確的寫法。由于我們使用了 hasOwnProperty,所以這次只輸出 moo。如果不使用 hasOwnProperty,則這段代碼在原生對象原型(比如 Object.prototype)被擴展時可能會出錯。

一個廣泛使用的類庫 Prototype 就擴展了原生的 JavaScript 對象。因此,但這個類庫被包含在頁面中時,不使用 hasOwnProperty 過濾的 for in 循環(huán)難免會出問題。

最佳實踐(Best practices)
推薦總是使用 hasOwnProperty。不要對代碼運行的環(huán)境做任何假設,不要假設原生對象是否已經(jīng)被擴展了。

typeof 操作符
typeof 操作符(和 `instanceof` 一起)或許是 JavaScript 中最大的設計缺陷,因為幾乎不可能從它們那里得到想要的結(jié)果。

盡管 instanceof 還有一些極少數(shù)的應用場景,typeof 只有一個實際的應用(譯者注:這個實際應用是用來檢測一個對象是否已經(jīng)定義或者是否已經(jīng)賦值),而這個應用卻不是用來檢查對象的類型。

注意: 由于 typeof 也可以像函數(shù)的語法被調(diào)用,比如 typeof(obj),但這并是一個函數(shù)調(diào)用。那兩個小括號只是用來計算一個表達式的值,這個返回值會作為 typeof 操作符的一個操作數(shù)。實際上不存在名為 typeof 的函數(shù)。

JavaScript 類型表格(The JavaScript type table)
Value Class Type
-------------------------------------
"foo" String string
new String("foo") String object
1.2 Number number
new Number(1.2) Number object
true Boolean boolean
new Boolean(true) Boolean object
new Date() Date object
new Error() Error object
[1,2,3] Array object
new Array(1, 2, 3) Array object
new Function("") Function function
/abc/g RegExp object (function in Nitro/V8)
new RegExp("meow") RegExp object (function in Nitro/V8)
{} Object object
new Object() Object object
上面表格中,Type 一列表示 typeof 操作符的運算結(jié)果??梢钥吹剑@個值在大多數(shù)情況下都返回 "object"。

Class 一列表示對象的內(nèi)部屬性 [[Class]] 的值。

JavaScript 標準文檔中定義: [[Class]] 的值只可能是下面字符串中的一個: Arguments, Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, String.

為了獲取對象的 [[Class]],我們需要使用定義在 Object.prototype 上的方法 toString。

對象的類定義(The Class of an object)
JavaScript 標準文檔只給出了一種獲取 [[Class]] 值的方法,那就是使用 Object.prototype.toString。
復制代碼 代碼如下:

function is(type, obj) {
var clas = Object.prototype.toString.call(obj).slice(8, -1);
return obj !== undefined && obj !== null && clas === type;
}

is('String', 'test'); // true
is('String', new String('test')); // true

上面例子中,Object.prototype.toString 方法被調(diào)用,this 被設置為了需要獲取 [[Class]] 值的對象。

譯者注:Object.prototype.toString 返回一種標準格式字符串,所以上例可以通過 slice 截取指定位置的字符串,如下所示:
復制代碼 代碼如下:

Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(2) // "[object Number]"

ES5 提示: 在 ECMAScript 5 中,為了方便,對 null 和 undefined 調(diào)用 Object.prototype.toString 方法,其返回值由 Object 變成了 Null 和 Undefined。

譯者注:這種變化可以從 IE8 和 Firefox 4 中看出區(qū)別,如下所示:
復制代碼 代碼如下:

// IE8
Object.prototype.toString.call(null) // "[object Object]"
Object.prototype.toString.call(undefined) // "[object Object]"

// Firefox 4
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
測試為定義變量(Testing for undefined variables)
typeof foo !== 'undefined'

上面代碼會檢測 foo 是否已經(jīng)定義;如果沒有定義而直接使用會導致 ReferenceError 的異常。這是 typeof 唯一有用的地方。

結(jié)論(In conclusion)
為了檢測一個對象的類型,強烈推薦使用 Object.prototype.toString 方法;因為這是唯一一個可依賴的方式。正如上面表格所示,typeof 的一些返回值在標準文檔中并未定義,因此不同的引擎實現(xiàn)可能不同。

除非為了檢測一個變量是否已經(jīng)定義,我們應盡量避免使用 typeof 操作符。

instanceof 操作符
instanceof 操作符用來比較兩個操作數(shù)的構(gòu)造函數(shù)。只有在比較自定義的對象時才有意義。如果用來比較內(nèi)置類型,將會和 typeof 操作符 一樣用處不大。

比較自定義對象(Comparing custom objects)
復制代碼 代碼如下:

function Foo() {}
function Bar() {}
Bar.prototype = new Foo();

new Bar() instanceof Bar; // true
new Bar() instanceof Foo; // true

// 如果僅僅設置 Bar.prototype 為函數(shù) Foo 本省,而不是 Foo 構(gòu)造函數(shù)的一個實例
Bar.prototype = Foo;
new Bar() instanceof Foo; // false
`instanceof` 比較內(nèi)置類型(Using `instanceof` with native types)
new String('foo') instanceof String; // true
new String('foo') instanceof Object; // true

'foo' instanceof String; // false
'foo' instanceof Object; // false

有一點需要注意,instanceof 用來比較屬于不同 JavaScript 上下文的對象(比如,瀏覽器中不同的文檔結(jié)構(gòu))時將會出錯,因為它們的構(gòu)造函數(shù)不會是同一個對象。

結(jié)論(In conclusion)
instanceof 操作符應該僅僅用來比較來自同一個 JavaScript 上下文的自定義對象。正如 `typeof` 操作符一樣,任何其它的用法都應該是避免的。

相關(guān)文章

  • 一個js控制的導航菜單實例代碼

    一個js控制的導航菜單實例代碼

    這篇文章主要是對js控制的導航菜單實例代碼進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-12-12
  • layui實現(xiàn)checkbox的目錄樹tree的例子

    layui實現(xiàn)checkbox的目錄樹tree的例子

    今天小編就為大家分享一篇layui實現(xiàn)checkbox的目錄樹tree的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • Next項目路徑添加指定的訪問前綴方法詳解

    Next項目路徑添加指定的訪問前綴方法詳解

    這篇文章主要介紹了Next項目路徑添加指定的訪問前綴方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • JavaScript 語法集錦 腳本之家基礎推薦

    JavaScript 語法集錦 腳本之家基礎推薦

    JavaScript語法集錦是對javascript常用函數(shù)的一些小結(jié),比較實用,建議收藏,方便查找需要的資料。
    2009-11-11
  • JavaScript使用AOP編程思想實現(xiàn)監(jiān)聽HTTP請求

    JavaScript使用AOP編程思想實現(xiàn)監(jiān)聽HTTP請求

    這篇文章主要為大家詳細介紹了如何在JavaScript使用AOP編程思想實現(xiàn)監(jiān)聽HTTP請求,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-02-02
  • js+css實現(xiàn)紅包雨效果

    js+css實現(xiàn)紅包雨效果

    這篇文章主要為大家詳細介紹了js+css實現(xiàn)紅包雨效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • 微信小程序常用簡易小函數(shù)總結(jié)

    微信小程序常用簡易小函數(shù)總結(jié)

    這篇文章主要介紹了微信小程序常用簡易小函數(shù),結(jié)合實例形式總結(jié)分析了微信小程序提示、登陸、驗證、session操作等相關(guān)操作函數(shù)與使用技巧,需要的朋友可以參考下
    2019-02-02
  • js實現(xiàn)封裝jQuery的簡單方法與鏈式操作詳解

    js實現(xiàn)封裝jQuery的簡單方法與鏈式操作詳解

    這篇文章主要給大家介紹了關(guān)于js實現(xiàn)封裝jQuery的簡單方法與鏈式操作的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • js實現(xiàn)簡易點擊切換顯示或隱藏

    js實現(xiàn)簡易點擊切換顯示或隱藏

    這篇文章主要為大家詳細介紹了js實現(xiàn)簡易點擊切換顯示或隱藏,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • js獲取url參數(shù)值的兩種方式

    js獲取url參數(shù)值的兩種方式

    js獲取url參數(shù)值的方法有很多,下面也為大家介紹兩種,喜歡的朋友可以測試下,希望對大家有所幫助
    2013-09-09

最新評論