2012-07-10 63 views
0

我發現自己處於一個有趣的狀態。我正在使用對象字面值來表示真實世界中的產品。現在每個產品都有一個與其相關的長度以用於運輸目的。它看起來像這樣:重寫對象的長度屬性

var product = { 
    name: 'MacBook Pro 15 Inch', 
    description: 'The new macbook pros....', 
    length: 15 
    height: 15 
    Weight: 4 
} 

這工作正常。但對於長度未知的產品,其默認長度爲-1。

同樣,這工作得很好,直到你試着這樣做:

console.log('Product has the following properties'); 
_.each(product, function(val, key) { 
    console.log(key + ":" + val); 
}); 

無鑰匙將被打印爲具有的-1長度的產品。爲什麼?那麼因爲內部下劃線使用length屬性,所以Javascript中的每個對象都必須遍歷傳入對象的所有屬性。由於我們重寫了該值,因此現在爲-1,並且自從我們開始循環i = 0以來,循環將永遠不會執行。

現在對於這個問題,我該如何防止長度屬性被覆蓋?最好的做法,以防止這種情況發生也將不勝感激。

回答

1

試試這個:

var product = { 
     name: "MacBook Pro 15 Inch", 
     description: 'The new macbook pros....', 
     length: 15, 
     height: 15, 
     weight: 4 
    }; 
    console.log('Product has the following properties'); 
    _.each(_.keys(product), function(key){ 
     console.log(key + ":" + product[key]); 
    }); 
1

這可能是由於_each函數中的一些魔術,因爲我懷疑它同時接受Object s和Array s ..製作你自己的?

簡單實現(避免一些常見的陷阱):

function each(obj, map_func) { 
    var key; 
    for (key in obj) { 
     if (Object.prototype.hasOwnerProperty.call(obj, key)) { 
      map_func(key, obj[key]); 
     } 
    } 
} 

_神奇的each可能是由於一個討厭的‘看‘像數組,但不是活得’有東西在JavaScript的’習慣實際上數組,像魔法變量arguments,我認爲options在選擇DOM元素中也是如此。

1

我想不出任何超越它的副手。我想使用length屬性是鴨子打字的一種形式,它通過jQuery將其標記爲可迭代的。

但是...你可以不能使用 jQuery的每一個方法,並做手工的方式..

通過簡單地使用

for (key in product) { 


} 

你得到你的基本循環。現在,如果您可能覆蓋對象的原型,則還應該檢查product.hashOwnProperty(key)以確保您正在迭代的當前鍵在產品實例中定義。

現在,如果你還需要一個新的封閉範圍,這是相當簡單的太..這裏是一個替代的每個功能..

var myEach = function(subject, callback) { 

    for (key in subject) { 

    if (subject.hasOwnProperty(key)) { 
     callback(subject[key], key); 
    } 
    } 

} 

注:未經測試。

+0

我想在這裏指出你的對象可以覆蓋hasOwnProperty屬性的'陷阱',所以使用'Object.prototype.hasOwnProperty',這是你想要的功能。 – Halcyon 2012-07-10 23:50:41

+0

不錯但有效的邊緣:) – Evert 2012-07-10 23:52:20

+0

我知道的權利。這就是爲什麼我們不能擁有美好的事物! – Halcyon 2012-07-10 23:53:26

1

如果你不能改變length屬性的名稱,你可以添加額外的檢查,以強調防止這種情況:

_.each = _.forEach = function(obj, iterator, context) { 
    if (obj == null) return; 
    if (Array.prototype.forEach && obj.forEach === Array.prototype.forEach) { 
    obj.forEach(iterator, context); 
    } else if (obj.length === +obj.length && obj.constructor != Object) { 
    for (var i = 0, l = obj.length; i < l; i++) { 
     if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return; 
    } 
    } else { 
    for (var key in obj) { 
     if (_.has(obj, key)) { 
     if (iterator.call(context, obj[key], key, obj) === breaker) return; 
     } 
    } 
    } 
}; 

加入這裏是第5行的&& obj.constructor != Object。它的工作原理雖然monkeypatching下劃線可能不是世界上最令人嚮往的東西。

編輯:實際上,這樣就破壞了像arguments這樣的僞數組,因爲它的構造函數是Object,但<an array-like object>.hasOwnProperty(<an integer>)是錯誤的。 Woo JavaScript。