最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Array 構(gòu)造函數(shù)
由于 Array 的構(gòu)造函數(shù)在如何處理參數(shù)時(shí)有點(diǎn)模棱兩可,因此總是推薦使用數(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
由于只有一個(gè)參數(shù)傳遞到構(gòu)造函數(shù)中(譯者注:指的是 new Array(3); 這種調(diào)用方式),并且這個(gè)參數(shù)是數(shù)字,構(gòu)造函數(shù)會返回一個(gè) length 屬性被設(shè)置為此參數(shù)的空數(shù)組。需要特別注意的是,此時(shí)只有 length 屬性被設(shè)置,真正的數(shù)組并沒有生成。譯者注:在 Firebug 中,你會看到 [undefined, undefined, undefined],這其實(shí)是不對的。在上一節(jié)有詳細(xì)的分析。

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

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

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

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

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

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

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

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

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

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

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

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

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

typeof 操作符
typeof 操作符(和 `instanceof` 一起)或許是 JavaScript 中最大的設(shè)計(jì)缺陷,因?yàn)閹缀醪豢赡軓乃鼈兡抢锏玫较胍慕Y(jié)果。

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

注意: 由于 typeof 也可以像函數(shù)的語法被調(diào)用,比如 typeof(obj),但這并是一個(gè)函數(shù)調(diào)用。那兩個(gè)小括號只是用來計(jì)算一個(gè)表達(dá)式的值,這個(gè)返回值會作為 typeof 操作符的一個(gè)操作數(shù)。實(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 操作符的運(yùn)算結(jié)果。可以看到,這個(gè)值在大多數(shù)情況下都返回 "object"。

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

JavaScript 標(biāo)準(zhǔn)文檔中定義: [[Class]] 的值只可能是下面字符串中的一個(gè): Arguments, Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, String.

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

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

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 被設(shè)置為了需要獲取 [[Class]] 值的對象。

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

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ū)別,如下所示:
復(fù)制代碼 代碼如下:

// 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)定義;如果沒有定義而直接使用會導(dǎo)致 ReferenceError 的異常。這是 typeof 唯一有用的地方。

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

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

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

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

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

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

// 如果僅僅設(shè)置 Bar.prototype 為函數(shù) Foo 本省,而不是 Foo 構(gòu)造函數(shù)的一個(gè)實(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

有一點(diǎn)需要注意,instanceof 用來比較屬于不同 JavaScript 上下文的對象(比如,瀏覽器中不同的文檔結(jié)構(gòu))時(shí)將會出錯(cuò),因?yàn)樗鼈兊臉?gòu)造函數(shù)不會是同一個(gè)對象。

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

相關(guān)文章

  • JavaScript繼承與多繼承實(shí)例分析

    JavaScript繼承與多繼承實(shí)例分析

    這篇文章主要介紹了JavaScript繼承與多繼承,結(jié)合實(shí)例形式較為詳細(xì)的分析了JavaScript繼承與多繼承的概念、原理、實(shí)現(xiàn)與使用方法,需要的朋友可以參考下
    2018-05-05
  • 原生js實(shí)現(xiàn)jquery函數(shù)animate()動(dòng)畫效果的簡單實(shí)例

    原生js實(shí)現(xiàn)jquery函數(shù)animate()動(dòng)畫效果的簡單實(shí)例

    下面小編就為大家?guī)硪黄鷍s實(shí)現(xiàn)jquery函數(shù)animate()動(dòng)畫效果的簡單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-08-08
  • javascript 數(shù)組排序函數(shù)

    javascript 數(shù)組排序函數(shù)

    javascript的數(shù)組排序函數(shù) sort方法,默認(rèn)是按照ASCII 字符順序進(jìn)行升序排列。
    2009-08-08
  • 解決頁面js接受Long型損失精度問題(最新解決方案)

    解決頁面js接受Long型損失精度問題(最新解決方案)

    這篇文章主要介紹了解決頁面js接受Long型損失精度問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • JS簡單封裝的圖片無縫滾動(dòng)效果示例【測試可用】

    JS簡單封裝的圖片無縫滾動(dòng)效果示例【測試可用】

    這篇文章主要介紹了JS簡單封裝的圖片無縫滾動(dòng)效果,結(jié)合完整實(shí)例形式分析了javascript針對圖片無縫滾動(dòng)功能實(shí)現(xiàn)的具體操作技巧,包括鼠標(biāo)事件響應(yīng)、事件函數(shù)及頁面元素屬性動(dòng)態(tài)變換等相關(guān)操作技巧,需要的朋友可以參考下
    2017-03-03
  • 基于Three.js插件制作360度全景圖

    基于Three.js插件制作360度全景圖

    這篇文章主要介紹了基于Three.js插件制作的360度全景圖,代碼簡單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-11-11
  • 詳解TypeScript如何正確使用Declare關(guān)鍵字

    詳解TypeScript如何正確使用Declare關(guān)鍵字

    如果您編寫 TypeScript 代碼的時(shí)間足夠長,您就已經(jīng)看到過declare關(guān)鍵字,但它有什么作用,為什么要使用它呢,下面小編就來和大家簡單講講
    2023-08-08
  • 微信小程序?qū)崿F(xiàn)手指拖動(dòng)選項(xiàng)排序

    微信小程序?qū)崿F(xiàn)手指拖動(dòng)選項(xiàng)排序

    這篇文章主要介紹了微信小程序?qū)崿F(xiàn)手指拖動(dòng)選項(xiàng)排序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • 微信小程序onShareTimeline()實(shí)現(xiàn)分享朋友圈

    微信小程序onShareTimeline()實(shí)現(xiàn)分享朋友圈

    這篇文章主要給大家介紹了關(guān)于微信小程序onShareTimeline()實(shí)現(xiàn)分享朋友圈的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 微信公眾平臺 發(fā)送模板消息(Java接口開發(fā))

    微信公眾平臺 發(fā)送模板消息(Java接口開發(fā))

    這篇文章主要介紹了微信公眾平臺 發(fā)送模板消息(Java接口開發(fā)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04

最新評論

弋阳县| 岚皋县| 辽中县| 潢川县| 井陉县| 江阴市| 麻阳| 红安县| 河东区| 松江区| 双牌县| 吴旗县| 阿拉善盟| 韶山市| 德化县| 连江县| 平果县| 枣庄市| 宜阳县| 铁岭县| 包头市| 镇安县| 四会市| 新民市| 体育| 禄丰县| 禹城市| 沙河市| 紫阳县| 丹东市| 鹤山市| 安新县| 丰都县| 莱阳市| 和田县| 绥芬河市| 萝北县| 叙永县| 襄垣县| 定陶县| 四会市|