76

可能重复:
如何检查对象是否在 JavaScript 中具有特定属性?

我在 Twitter 的 JavaScript 文件中找到了以下代码段。为什么他们需要调用hasOwnProperty函数才能看到dict属性keyfor循环针对 'dict' 中的每个 'key' 运行,这意味着 'dict' 具有 'key'。我错过了一点吗?

function forEach(dict, f) {
    for (key in dict) {
        if (dict.hasOwnProperty(key))
            f(key, dict[key]);
    }
}
4

4 回答 4

78

因为如果您不这样做,它将遍历原型链上的每个属性,包括您不知道的属性(可能是由弄乱本机对象原型的人添加的)。

这样,您只能保证该对象实例本身上的键。

于 2012-10-04T20:57:34.273 回答
36

hasOwnProperty方法让您知道属性是直接在对象的实例上还是从其原型链继承。

考虑以下

function ObjWithProto() {
    this.foo = 'foo_val';
}

ObjWithProto.prototype = {bar: 'bar_val'};

var dict = new ObjWithProto();
dict.foobar = 'foobar_val';

即,您有一个具有属性的对象 ,并且它还从其原型链继承了一个属性。dictfoofoobarbar

现在通过您的代码(的修改版本)运行它:

function forEach(dict) {
    var key;
    for (key in dict) {
        if (dict.hasOwnProperty(key)) 
            console.log('has', key, dict[key]);
        else 
            console.log('not', key, dict[key]);
    }
}
forEach(dict);

你会看见

has foo foo_val
has foobar foobar_val
not bar bar_val

这使您可以将对象本身的属性和它继承的属性(通常是与循环无关的方法)分开。

此外,如果您现在这样做dict.bar = 'new_bar_val';,最后的结果将变为has bar new_bar_val,让您甚至可以区分与继承的同名的属性。

于 2012-10-04T21:09:08.360 回答
5

JavaScript 中的每个对象都是一个字典。这意味着“toString”和其他所有方法都是每个对象的键:

var myObj = {};
console.log(myObj["toString"]);

但是这个函数是继承自 Object 类的,所以 hasOwnProperty 会告诉你这个键是由字典拥有还是被继承。

"toString" in myObj; // true
myObj.hasOwnProperty("toString") // false
于 2012-10-04T20:59:19.413 回答
1

笨蛋就在这里。例如,Prototype.js 框架用于使用额外的辅助方法扩展原生数组(我不知道当前框架版本的情况)。

因此,直接使用“for (key in dict)”将返回 div 的所有元素以及对辅助方法的引用。这有点出乎意料:)

于 2012-10-04T21:02:19.413 回答