Javascript中未定义和未定义之间的区别

Ste*_*ven 25 javascript

有关简单的示例,请参见http://jsfiddle.net/FDhQF/1/.

未定义的内容与Javascript中未定义的内容之间有什么区别?例如,尝试访问未定义的对象的属性(实际上,尝试访问变量)将返回undefined.但你也可以设置一些东西= undefined.当你这样做,尝试访问它仍然返回undefined,但指针仍然存在.如上所示,一个例子是如何迭代对象仍然遍历您已经(重新)声明为未定义的属性.看起来有两种不同的未定义.任何人都可以对这种情况有所了解吗?

CMS*_*CMS 42

访问未在对象上定义的属性和包含原始undefined值的属性都将返回给您undefined.

例如:

var obj = {
  a: undefined
};

obj.a; // undefined
obj.b; // undefined
Run Code Online (Sandbox Code Playgroud)

不同的是,这a是一个自己的财产,而b不是:

obj.hasOwnProperty('a'); // true
obj.hasOwnProperty('b'); // false
Run Code Online (Sandbox Code Playgroud)

在第一种情况下a是一个自己的属性,即使它包含undefined其值.在第二种情况下,b不是自己的属性,访问obj.bb在原型链中寻找一个名为的属性.

当原型链结束时(当它到达带有a的对象时null [[Prototype]]),属性查找结束并undefined显式返回.

您应该知道该hasOwnProperty方法只检查该对象是否物理存在于对象(自己的属性)上,但我们还继承了属性,对于这种情况,我们可以使用in运算符,例如:

function Test () {}
Test.prototype.a = 'foo'; // instances of Test will inherit from Test.prototype

var obj = new Test(); // { a="foo",  b="bar"}
obj.b = 'bar';

obj.hasOwnProperty('a');  // false
'a' in obj;               // true
obj.a;                    // 'foo'

obj.hasOwnProperty('b');  // true
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,obj继承自Test.prototype,并且a属性不是自己的属性,但它可以通过原型链获得.这就是hasOwnProperty返回falsein运营商返回的原因true.

您可以看到[[Get]]内部操作如何解析内部属性

笔记:

  • undefined在ECMAScript 3(语言标准的最广泛实现版本)上访问作为标识符不被认为是安全的,因为不是语言关键字(null例如),它只是全局对象的属性,它是在此版本的规范中可写,这意味着如果有人替换其值(例如window.undefined = 'LOL';),它将破坏您的代码.

可以使用@strager提及的typeof运算符,例如:

if (typeof obj.prop == 'undefined') { /*....*/ }
Run Code Online (Sandbox Code Playgroud)

此运算符始终返回一个字符串(可以安全使用==:),其值取决于其操作数的类型,此处描述了可能的值.

解决此问题的另一种常见方法是声明您自己的undefined变量,可在函数范围内使用,例如,某些库使用以下模式:

(function(undefined) {
  // code here
})();
Run Code Online (Sandbox Code Playgroud)

该函数有一个名为的参数undefined,它立即执行而不传递任何值(最后一对或者是parens进行调用).

也许值得一提的是,undefined全局属性最终在ECMAScript 5中被描述为不可写(不可变,以及不可枚举和不可配置 - 非可删除 - ).

  • hasOwnProperty直接从对象实例使用该方法也不被认为是安全的,因为如果某个对象具有相同名称的属性,则原始方法将被遮蔽.例如:

    var obj = { hasOwnProperty: function () { /* evil code :) */ } };
    
    Run Code Online (Sandbox Code Playgroud)

如果你打电话:

    obj.hasOwnProperty('prop'); 
Run Code Online (Sandbox Code Playgroud)

将执行在对象上定义的方法(并且您不希望这样,因为您确切地知道要调用哪个方法...),因为它会影响该方法Object.prototype,但是可以通过以下方式安全地调用它:

    Object.prototype.hasOwnProperty.call(obj, 'prop');
Run Code Online (Sandbox Code Playgroud)