2017-01-12 151 views
3

提供的對象可能包含自己的財產被稱爲「hasOwnProperty」:什麼是適當的/推薦的方式來使用hasOwnProperty?

> a={abc: 123}; 
{ abc: 123 } 
> a.hasOwnProperty("abc"); 
true 
> a['hasOwnProperty'] = 1; 
1 
> a.hasOwnProperty("abc"); 
TypeError: a.hasOwnProperty is not a function 
... 

這工作,有點醜陋的界面,如果你仔細想想Object.keys(),Object.assign()等。所以,是有更好的方法嗎?

> Object.hasOwnProperty.call(a, "abc"); 
true 
> Object.hasOwnProperty.call(a, "hasOwnProperty"); 
true 

爲什麼不應該解決方案是唯一的推薦方式?直接從對象中使用方法看起來像是一個失敗的祕訣,尤其是如果它包含外部數據(不是在一個人的控制下)。

+0

可能會有所幫助:http://stackoverflow.com/questions/12017693/why-use-object-prototype-hasownproperty -callmyobj-prop-instead-of-myobj-hasow – tymeJV

回答

0

使用hasOwnProperty的適當/推薦方法是作爲過濾器或者判斷是否一個對象......好吧,有這個屬性。就他們的方式,你在第二個命令a.hasOwnProperty('abc')中使用它。

通過用a['hasOwnProperty'] = 1覆蓋Object hasOwnProperty屬性,雖然它是安全有效的,但只是刪除了在該對象上使用hasOwnProperty函數的功能。

我在這裏錯過了你的真實問題嗎?看起來你已經知道你的例子。

使用方法直接從一個對象

」似乎是一個失敗

你指的是這樣的一個偏方:

> dog = {speak: function() {console.log('ruff! ruff!')}}; 
> dog.speak(); // ruff! ruff! 

因爲那是非常你可以想象很多方面的用處。

+0

我指的是將數據(如標記文檔)加載到對象中。該文件可能是關於JavaScript,可能包含標記'hasOwnProperty'。當然,使用方法的對象是強大的,但這不是我的問題。 – niry

0

如果你可以使用ECMAScript 2015,你可以試試Reflect.getOwnPropertyDescriptor。 它返回給定屬性的屬性描述符(如果它存在於該對象上),否則爲undefined。

爲了簡化你可以創建這個函數:

var hasOwnProp = (obj, prop) => Reflect.getOwnPropertyDescriptor(obj, prop) !== undefined; 

var obj = new Object(); 
 
obj.prop = 'exists'; 
 

 
console.log('Using hasOwnProperty') 
 
console.log('prop: ' + obj.hasOwnProperty('prop'));    
 
console.log('toString: ' + obj.hasOwnProperty('toString'));   
 
console.log('hasOwnProperty: ' + obj.hasOwnProperty('hasOwnProperty')); 
 

 
var hasOwnProp = (obj, prop) => Reflect.getOwnPropertyDescriptor(obj, prop) !== undefined; 
 

 
console.log('Using getOwnPropertyDescriptor') 
 
console.log('prop: ' + hasOwnProp(obj, 'prop')); 
 
console.log('toString: ' + hasOwnProp(obj, 'toString')); 
 
console.log('hasOwnProperty: ' + hasOwnProp(obj, 'hasOwnProperty')); 
 

 
obj['hasOwnProperty'] = 1; 
 

 
console.log('hasOwnProperty: ' + hasOwnProp(obj, 'hasOwnProperty'));

+0

感謝您指出'Reflect.getOwnPropertyDescriptor()'。用什麼方法比Object.hasOwnProperty.call(obj,prop)更好? – niry

0

任何內置可在JS被覆蓋 - 這通常被認爲是最好的做法,以避免覆蓋任何本地方法,其中可能。如果原始功能保留,那麼它仍然可以正常工作,如果再次正確覆蓋,甚至可能會進一步擴展。

由於這被認爲是最佳做法,我建議重新映射鍵以避免覆蓋它們。如果重新映射密鑰不是一種選擇,那麼你可以通過本地引用/包裝Object.hasOwnPropertyObject.prototype.hasOwnProperty使其感覺不那麼麻煩。在hasOwnProperty的情況下,你可能實現一個迭代器(對可枚舉的非繼承屬性進行迭代是hasOwnProperty的一種非常常見的用法),以減少它的使用可能性。總會有人對你的對象不太熟悉的風險試圖直接迭代,所以我真的覺得密鑰映射更安全,即使它在服務器端密鑰和本地密鑰之間造成輕微的差異。

鍵映射可以像使用hasOwnProperty_data代替hasOwnProperty這意味着對象將像預期的那樣和IDE的自動完成功能可能仍然會足夠接近知道什麼屬性表示後綴一樣簡單。

映射函數可能看起來像下面這樣:

function remapKeys(myObj){ 
 
    for(var key in myObj){ 
 
     if(Object.prototype.hasOwnProperty.call(myObj, key)){  
 
     if((key in Object) && Object[key] !== myObj[key]){ // Check key is present on Object and that it's different ie an overridden property 
 
      myObj[key + "_data"] = myObj[key]; 
 
      delete myObj[key]; // Remove the key 
 
     } 
 
     } 
 
    } 
 
    return myObj; // Alters the object directly so no need to return but safer 
 
} 
 

 
// Test 
 
var a = {}; 
 
a.hasOwnProperty = function(){ return 'overridden'; }; 
 
a.otherProp = 'test'; 
 
remapKeys(a); 
 
console.log(a); // a { hasOwnProperty_data : function(){ return 'overridden';}, otherProp: 'test' } 
 
console.log(a.hasOwnProperty('otherProp')); // true

+0

這似乎是很多開銷(內存和代碼)試圖避免覆蓋內置方法。我更喜歡用'Object.create(null)'確保它沒有任何方法' – niry

+0

您只需要前11行,並且只能在加載數據後運行一次。內存佔用這將是最小的它修改對象的地方不克隆它等我認爲這是一個小的代價來支付訪問內置和避免混淆。我認爲我的例子沒有處理的唯一考慮事項是嵌套對象 - 重構這個以使用遞歸將處理這些。第二個原因是與「僅附加後綴」相比,「自定義映射」可能是有益的。使用null原型創建對象可能與重寫內置插件一樣令人困惑。 – Brian

相關問題