雲栖号資訊:【 點選檢視更多行業資訊】
在這裡您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!
雖然已知for...in會周遊對象原型鍊上的屬性,但心想用于字面量建立的對象應該沒有什麼大問題,于是便棄hasOwnProperty于不顧,最終被工單教做人了。在修複中總結了幾個可以讓周遊對象更加優雅的方法。
for...in踩坑複盤
能不能去掉hasOwnProperty?
for...in常用于周遊對象或者數組,比如
const obj = {
a: 1,
b: 2
};
for (const key in obj) {
console.log(key, obj[key]);
}
// 輸出
// a 1
// b 2
我們都知道for...in會周遊原型鍊上的屬性,是以一般會結合hasOwnProperty來判斷屬性是否在對象自身上,而不是在原型鍊上。
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key]);
}
}
可每次都要多增加一行代碼,多一個縮進,實在麻煩,能不能偷懶不加hasOwnProperty?
于是我動起了小心思,使用字面量建立的對象或者數組,不是類的執行個體,原型鍊上幹幹淨淨的,那周遊的時候也沒必要判斷了吧。于是就在周遊字面量對象時放心大膽地把hasOwnProperty抛棄了。
工單打臉
我負責的産品是API,使用者在自己的頁面應用中引入使用。某天,有使用者回報若同時引入我家API和另一個腳本庫就會引發報錯:

調試發現報錯發生在:
renderLayers是一個數組,這裡原本是周遊可渲染圖層進行操作,而圖層對象都有isHidden方法,為何報錯呢?原因是使用者另引入的腳本對Object、Array、String等基礎引用類型的原型鍊做了擴充,加入了一些方法。是以在for...in周遊renderLayers時,也周遊到了addRange、clear這些屬性,layer則指派為一個function,而不是圖層對象。
for(var prop in source) {
if(replace == false && dest[prop] != null) { continue; }
dest[prop] = source[prop];
}
return dest;
};
Object.extend(Array.prototype, {
addRange: function(items) {
if(items.length > 0) {
for(var i=0; i < items.length; i++) {
this.push(items[i]);
}
}
},
clear: function() {
this.length = 0;
return this;
},
// ...
}, false);
避坑指南
如上所述,隻能開始内部大清理,所有使用for...in而沒有帶hasOwnProperty的地方都需要進行改造。除了加上hasOwnProperty進行判斷之外,視具體情況還可以使用以下方法,讓你的代碼更加優雅:
1. 數組盡量使用forEach進行周遊
比如引發報錯的這一段,renderLayers是一個數組,直接使用forEach進行周遊即可:
2. 對象深拷貝盡量使用解構指派
for...in可周遊對象屬性實作一一指派完成簡單的對象深拷貝,這種操作可以用解構指派來實作,更簡單。
return {...obj};
}
const obj = {
a: 1
};
const objCopy = copy(obj);
console.log(objCopy);
// 輸出:{a: 1}
3. 周遊鍵值可以結合Object.entries()和forEach
Object.entries()傳回對象所有鍵值對組成的數組,再結合forEach即可完成周遊。若隻是周遊對象的鍵或者值,可以使用Object.keys()和Object.values()。
在改造過程中,可以抽象出一個forIn方法作為工具函數,這樣多處調用就可以省掉不少備援代碼啦~
Object.entries(obj).forEach(entry => {
callback(...entry);
});
}
const obj = {
a: 1
};
forIn(obj, (key, value) => {
console.log(key, value);
});
// 輸出:a 1
4. 若要使用break、return提前結束循環,需結合for...of
方法3雖好,但使用forEach沒辦法中斷循環,這時候可以使用for...of,也是非常簡潔的。
a: 1,
b: 2
};
for (let [key, value] of Object.entries(obj)) {
if (value > 1) {
break;
}
console.log(key, value);
}
// 輸出:a 1
【雲栖号線上課堂】每天都有産品技術專家分享!
課程位址:
https://yqh.aliyun.com/live立即加入社群,與專家面對面,及時了解課程最新動态!
【雲栖号線上課堂 社群】
https://c.tb.cn/F3.Z8gvnK
原文釋出時間:2020-06-03
本文作者:多多洛愛學習
本文來自:“
掘金”,了解相關資訊可以關注“掘金”