使用Object.hasOwnProperty与测试属性是否未定义的好处

27

由于 hasOwnProperty 具有某些警告和瑕疵(在Internet Explorer 8中的窗口/广泛使用等问题):

是否有任何理由使用它?如果只是测试属性是否未定义,是更合理和更简单的方法吗?

例如:

var obj = { a : 'here' };

if (obj.hasOwnProperty('a')) { /* do something */ }

if (obj.a !== undefined) { /* do something */ }
// Or maybe (typeof (obj.a) !== 'undefined')

我希望使用最跨浏览器友好且最新的方法。

我也看到了针对hasOwnProperty重写的这个原型,虽然它可行,但我对它的有用性并不确定...

if (!Object.prototype.hasOwnProperty) {
    Object.prototype.hasOwnProperty = function(prop) {
        var proto = this.__proto__ || this.constructor.prototype;
        return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]);
    };
}

1
除了使用hasOwnProperty之外,任何其他方法都有可能产生错误的结果。 - Xotic750
如果我知道我正在寻找一个数组、对象或函数,我更喜欢它更简单:if (obj.a)。当然,如果 obj.a 可以是零、"" 或 false,则需要将其与 !== undefined 进行比较。此外,根据 ("a" in obj),此对象具有 "a",但不具有 if(obj.a): {a:undefined}。 - dandavis
1
附加信息:您可能会发现这个jsPerf测试很有趣:http://jsperf.com/hasownproperty-vs-in/2。底线是:`.hasOwnProperty`比任何其他测试属性存在的方式都要慢得多(对我来说这很令人惊讶)。 - Felix Kling
1
@FelixKling 有趣的jsperf。然而,.hasOwnPropertyin有非常不同的含义。引用Mozilla文档"obj.hasOwnProperty(prop)"用于确定对象是否具有该对象的直接属性作为指定属性;与in运算符不同,此方法不会检查对象的原型链。 - Adriano
3个回答

23

hasOwnProperty方法不检查undefined的值。它只检查一个属性是否被分配给对象,即使它是undefined:

var obj = { a : undefined };
obj.hasOwnProperty("a") // true
obj.a === undefined     // true
obj.hasOwnProperty("b") // false
obj.b === undefined     // true

22

hasOwnProperty方法检查属性是否直接分配给对象。

因此,如果属性'a'在原型中,hasOwnProperty将进行过滤。

function NewClass() {}
NewClass.prototype = { a: 'there' };
var obj = new NewClass();

if (obj.hasOwnProperty('a')) { /* Code does not work */ }
if (obj.a !== undefined) { /* Code works */ }

因此,在许多情况下,hasOwnProperty更安全。


非常正确... 发布问题后才意识到这一点!我很难找到支持hasOwnProperty的浏览器,它至少兼容IE7+吗? - Mark Pieszak - Trilon.io

4
作为对Pavel Gruba的回答的进一步信息,以及您提供的polyfil:
据我所知,在不支持它的浏览器中,没有好的方法来填充hasOwnProperty。我见过很多不同的填充方法,它们都会产生错误的正面或负面结果。如果我绝对没有其他选择,那么这就是我为自己创建的东西,但它也会出现错误的正面和负面结果。根据MSDN

在以下文档模式下受支持:Quirks、Internet Explorer 6标准、Internet Explorer 7标准、Internet Explorer 8标准、Internet Explorer 9标准、Internet Explorer 10标准。还支持Windows Store应用程序。

JavaScript

function is(x, y) {
    if (x === y) {
        if (x === 0) {
            return 1 / x === 1 / y;
        }

        return true;
    }

    var x1 = x,
        y1 = y;

    return x !== x1 && y !== y1;
}

function hasOwnProperty(object, property) {
    var prototype;

    return property in object && (!(property in (prototype = object.__proto__ || object.constructor.prototype)) || !is(object[property], prototype[property]));
}

function NewClass() {}
NewClass.prototype = {
    a: 'there'
};

var obj = new NewClass();

if (obj.hasOwnProperty("a")) {
    console.log("has property")
}

if (hasOwnProperty(obj, "a")) {
    console.log("has property")
}

在JSFiddle上


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接