JavaScript拥有OwnProperty与类型

JavaScript hasOwnProperty vs typeof

本文关键字:类型 OwnProperty 拥有 JavaScript      更新时间:2023-09-26

我在谷歌上搜索了很多,但找不到我要找的地方:

使用Object.hasOwnProperty与在属性未定义时进行测试的好处

jsperf速度测试

如何确定本机JavaScript对象是否具有属性/方法?

和许多其他网站,但这不是我要找的地方。我真正的问题是:

为什么hasOwnProperty在他的超类(原型)中找不到方法?为什么有人会使用hasOwnProperty?它比typeof慢得多,如果您使用继承,它就不起作用

第二个问题:

在这个问题中,Barney回答说您必须使用if ('property' in objectVar)来检查属性是否存在,但没有解释原因。有人知道你为什么要使用这种结构吗?

var objA = function(){};
objA.prototype.alertMessage = function(){
        return 'Hello A';
};
var objB = function(){
    this.hello = function(){
        return 'hello';
    };
};
// Inheritance
objB.prototype  = Object.create(objA.prototype);
objB.prototype.constructor = objA;
var test = new objB();
if (test.hasOwnProperty("alertMessage")){
    console.log("hasOwnProperty: " + test.alertMessage());
}
if (typeof test.alertMessage === "function"){
    console.log("typeof: " + test.alertMessage());
}
if (test.hasOwnProperty("hello")){
    console.log("hasOwnProperty: " + test.hello());
}
if (typeof test.hello === "function"){
    console.log("typeof: " + test.hello());
}

查看jsFiddle

使用(在某些情况下要使用)hasOwnProperty的原因有很多,以及为什么它的行为是这样的:

  • 顾名思义,hasOwnProperty检查测试的对象是否拥有具有给定名称的属性。如果它从另一个对象(其原型)继承了一个方法/属性,那么该属性的所有者不是该对象,而是其原型。因此,对象没有自己的名为X的属性
  • typeof在大多数情况下都可以工作,但对象可以是这样的:var o = {foo: undefined}。当然,在o.foo上使用typeof会产生"undefined",但对象确实拥有一个名为foo的属性
  • 使用if ('properyname' in object)是一种变通方法,它结合了两个世界的优点:在o = {foo: undefined};的情况下,它求值为true,而不需要查找hasOwnPropery方法(这是Object.prototype的一个属性)或具有上下文绑定的函数调用等开销。它还将在原型链中找到属性

因此,请考虑以下示例:

var o = {foo: undefined,
    toString: undefined};//overwrite inherited method
console.log(typeof o.foo);//undefined
console.log(typeof o.toString);//undefined
console.log(o.hasOwnProperty('toString'));//true
delete(o.toString);
console.log(typeof o.toString);//function
if ('valueOf' in o)
    console.log(o.valueOf === Object.prototype.valueOf);//true
if ('foo' in o)
    console.log(o.foo);//undefined

另一件需要注意的重要事情是,您关于hasOwnProperty在处理继承时不起作用的声明是完全错误的。在JS中使用的每个对象都至少继承一个原型。认识、理解和尊重这一点很重要。如果在对象上循环,建议确保实际在属于对象本身的属性上迭代。因此,这并不罕见:

for (p in obj)
{
    if (obj.hasOwnProperty(p))
        //process property
}

这是为了避免代码遍历原型链中的所有属性,这可能会破坏超级对象

if (!Object.prototype.hasProperty)
{//dirty check ;-P
    Object.prototype.hasProperty = (function(OP)
    {
        return function(name)
        {
            //typeof for speed: if value is not undefined, return true
            if (typeof this[name] !== 'undefined' || this.hasOwnProperty(name))
                return true;
            if (this === OP)//we've just checked the Object.prototype, found nothing, so return false
                return false;
            return Object.getPrototypeOf(this).hasProperty(name);//check prototype
        };
    }(Object.prototype));//OP is object prototype
}