2017-01-12 112 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

相关问题