Javascript 未定义,类型未定义,hasOwnProperty

Javascript 未定义,类型未定义,hasOwnProperty,javascript,Javascript,拿这个片段来说 var a = { } if(typeof a.c === 'undefined'){ console.log('inside if'); } if(a.c === undefined){ console.log('inside if'); } 如果if都会导致true特定于某些浏览器的这两种语句是否有任何区别? 另外,在我的上一个项目中,我已经多次使用typeof a.c==“undefined”来检查json数据中的值 现在,我知道这不是一个好方法,因为一些值可能也

拿这个片段来说

var a = {

}

if(typeof a.c === 'undefined'){
 console.log('inside if');
}
if(a.c === undefined){
 console.log('inside if');
}
如果
if
都会导致
true
特定于某些浏览器的这两种语句是否有任何区别?

另外,在我的上一个项目中,我已经多次使用
typeof a.c==“undefined”
来检查
json
数据中的值

现在,我知道这不是一个好方法,因为一些值可能也未定义,所以我的逻辑将失败

我应该使用
hasOwnProperty

但是我确信没有任何值是未定义的,我可以使用
typeof a.c==“undefined”
来代替
hasOwnProperty
,或者我应该用
hasOwnProperty

更改所有
typeof
更新:您可能想检查这个问题:)

非常旧的浏览器(Netscape 2、IIRC,可能还有IE 4或更低版本)中,无法将值与未定义的
进行比较,因为这会导致错误。然而,在任何(半)现代浏览器中,没有理由检查
类型的值==='undefined'
,而不是
值===undefined
(除了有人可能重新定义变量
undefined
的妄想症)

hasOwnProperty
有不同的用途。它检查对象是否具有具有给定名称的属性,而不是其原型;i、 e.无论继承的属性如何。如果要检查对象是否包含某个继承的属性,应使用
If('c'在a){

但基本上,这些可能都会起作用:

if (a.c === undefined) console.log('No c in a!');
if (typeof a.c === 'undefined') console.log('No c in a!');
if (!('c' in a)) console.log('No c in a!');
if (!a.hasOwnProperty('c')) console.log('No c in a!');
主要区别在于:

  • a.c===undefined
    如果有人做了
    undefined='defined'
    或类似的把戏,就会产生意想不到的结果
  • !('c'在a中)
    可读性不强(IMHO)
  • 如果对象
    a
    不包含属性
    c
    ,但其原型包含属性
    c
    ,则a.hasOwnProperty('c')
将返回
false
就我个人而言,我更喜欢第一个,因为它更具可读性。如果你有妄想症,想避免重新定义的
未定义的
,请将你的代码包装在一个自动执行的匿名函数中,如下所示:

(function (undefined) {
  // in here, 'undefined' is guaranteed to be undefined. :-)

  var a = {

  };

})();

如果您检查作为解析JSON字符串结果的标准对象,
.hasOwnProperty
没有明显的好处。当然,除非您或您正在使用的某个库与
对象.prototype混为一谈

一般来说,
未定义的
可以被重新定义,但我自己从未遇到过这种情况,我也不认为我会这样做。这是不可能的(AFAIK)把
typeof
的返回值弄乱。在这方面,后者是最安全的方法。我相信一些古老的浏览器也不能很好地处理
未定义的
关键字

在恢复过程中:无需去更换每一种
类型的
检查。就个人而言:我认为养成使用
.hasOwnProperty
的习惯是一种很好的做法。因此,我建议,如果某个属性可能存在,但尚未定义,
。hasOwnPorperty
是最安全的选择


<> >响应您的评论:是的,<代码>类型> <代码>将满足您的需要。95%的时间。<代码> .HasObjys/<代码>将工作99%次。但是,正如名称所示:不检查继承链上的属性,请考虑以下示例:

Child.prototype = new Parent();
Child.prototype.constructor=Child;//otherwise instance.constructor points to parent

function Parent()
{
    this.foo = 'bar';
}

function Child()
{
    this.bar = 'baz';
}

var kiddo = new Child();
if (kiddo.hasOwnProperty('foo'))
{
    console.log('This code won\'t be executed');
}
if (typeof kiddo.foo !== 'undefined')
{
    console.log('This will, foo is a property of Parent');
}
因此,如果您想检查单个对象是否有属性,则需要
hasOwnProperty
。特别是如果您要更改该属性的值(如果它是原型属性,则可以更改所有实例)。
如果您想知道某个属性是否有值(而不是
未定义的
),无论它位于继承链中的什么位置,您都需要
typeof
。我在某个地方有一个递归函数来确定在继承链中可以找到该属性的位置。一旦找到它,我也会将它发布到这里

更新:

正如承诺的那样,该函数用于在继承链中定位属性。它不是我不久前使用的实际函数,因此我编写了一份工作草案。它并不完美,但它可以很好地帮助您:

function locateProperty(obj,prop,recursion)
{
    recursion = recursion || false;
    var current = obj.constructor.toString().match(/function\s+(.+?)\s*\(/m)[1];
    if (!(obj.hasOwnProperty(prop)))
    {
        if (current === 'Function' || recursion === current)
        {
            return false;
        }
        return locateProperty(new window[current](),prop,current);
    }
    return current;
}
//using the object kiddo
locateProperty(kiddo,'foo');//returns 'Parent'
locateProperty(kiddo,'bar');//returns 'Parent', too
为了避免最后一个故障,您可以将最后一个
return current;
语句替换为
return obj;
。或者,更好的做法是,在上述代码段中添加以下行:

Child.prototype.constructor=Child;
我在第一次编辑时忘记了…

  • 将p的可枚举属性复制到o,然后返回o

  • 如果o和p有一个同名的属性,则o的属性将被单独保留

  • 此函数不处理getter和setter或复制属性

    function merge(o, p) 
    {
        for(prop in p) 
        {   
            // For all props in p.
            if (o.hasOwnProperty[prop]) continue;  // Except those already in o.
            o[prop] = p[prop];                     // Add the property to o.
        }
    
        return o;
    }
    

o.hasOwnProperty[prop]
o.hasOwnProperty(prop)
之间的区别是什么?

只是一个注释:下面是我看到它的操作方式:另一种方法:
如果(a.c===(函数(u){return u})(){
…类似的问题:@FlorianMargaine,在你的链接中,我看到
变量===void 0;
,现在是什么?@Jashwant
void操作符计算给定的表达式,然后返回未定义的表达式。
因此它计算
0
(这意味着它什么都不做)然后它返回
undefined
。在今天的Chrome版本中,
foo===undefined
会触发一个错误。请看下面的答案:同样,对于“偏执狂”,这就是为什么许多人使用以下技巧:
(函数(窗口,文档,未定义){/*您的代码*/}(窗口,文档))
:-)哦,你刚刚编辑添加了这个。@FlorianMargaine:Ah,
foo===undefined
是一个很好的参数。不过,使用
value===undefined
是一个更具说服力的参数,因为它允许你查找未声明的变量,这是一件非常糟糕的事情™.他们可以