繁体   English   中英

未定义,typeof undefined,hasOwnProperty

[英]Undefined, typeof undefined, hasOwnProperty

拿这个片段,

var a = {

}

if(typeof a.c === 'undefined'){
 console.log('inside if');
}
if(a.c === undefined){
 console.log('inside if');
}

if结果都是true 某些浏览器特定的两种语句有什么不同吗?

另外,在我的上一个项目中,我已经多次使用typeof ac == 'undefined'来检查json数据中的值。

现在,我知道这不是好方法,因为某些值也可能undefined ,因此我的逻辑将失败。

我应该使用hasOwnProperty

但我相信,没有值将undefined ,我可以使用typeof ac == 'undefined'代替hasOwnProperty或者我应该改变我所有typeofhasOwnProperty

更新 :你可能想看看这个问题: 变量=== undefined vs. typeof variable ===“undefined” )。

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

hasOwnProperty用于不同的目的。 它检查对象是否具有给定名称的属性, 而不是其原型 ; 即无论继承属性如何。 如果你想检查对象是否包含某个属性,是否继承,你应该使用if ('c' in 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!');

主要区别在于:

  • ac === undefined会产生一个意想不到的结果,如果有人做了undefined = 'defined'或一些这样的技巧;
  • !('c' in a)不太可读(恕我直言)
  • !a.hasOwnProperty('c')如果对象a不包含属性c ,则!a.hasOwnProperty('c')将返回false ,但其原型确实如此。

就个人而言,我更喜欢第一个,因为它更具可读性。 如果你是偏执狂并希望避免重新定义undefined的风险,请将代码包装在一个自执行的匿名函数中,如下所示:

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

  var a = {

  };

})();

如果检查标准对象是解析JSON字符串的结果,则.hasOwnProperty没有明显的好处。 当然,除非您正在使用的某个lib或者正在使用Object.prototype

一般来说, undefined可以重新定义,但我自己没有遇到过 - 我也不认为我会这样做。 然而,不可能(AFAIK)弄乱typeof的返回值。 在这方面,后者是最安全的方式。 我相信一些古老的浏览器也不能与undefined关键字一起使用。

在恢复:没有必要去和替换每一个typeof检查。 在个人方面:我认为养成使用.hasOwnProperty的习惯是一种好习惯。 因此,我建议,如果某个属性可能存在但尚未定义,则.hasOwnPorperty是最安全的选择。


回应您的评论:是的, typeof将满足您的需求~95%的时间。 .hasOwnProperty将工作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就是您所需要的。 特别是如果您要更改该属性的值(如果它是原型属性,则可以更改所有实例)。
如果你想知道一个属性是否有一个值(其他是undefined ),无论它在继承链中的位置,你都需要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;声明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)什么区别?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM