问题在于:
var x = 5;
window.x === x // true. x, as it seems, is a property of window
delete x; // false
delete window.x; // false;
BUT
window.x = 5;
delete window.x; // true
和
window.x = 5;
delete x; // true
这种行为的解释是什么?
答案 0 :(得分:4)
基本上,原因是声明的变量是使用内部DontDelete
属性创建的,而通过赋值创建的属性则不是。
以下是解释delete
:Understanding delete
当声明的变量和函数成为变量的属性时 object - 激活对象(用于功能代码)或全局 对象(对于全局代码),这些属性是使用DontDelete创建的 属性。但是,任何显式(或隐式)属性赋值 创建没有DontDelete属性的属性。这是必要的 为什么我们可以删除一些属性,而不是其他属性:
答案 1 :(得分:2)
您只能将delete
用于删除对象,对象属性或数组元素。
如果无法表示 表达式 ,则删除 表达
delete
将无效
作为财产。因此delete
可以删除全局变量,但不能删除var
所引用的变量。
所以,让我解释一下:
var x = 5;
您可以通过var创建全局范围内的变量,而不是window对象的属性。这个var只链接到window.x.然后你比较window.x === x
它将返回true。但是:
delete x; // deleting variable, not property, return false
delete window.x; // resolve link to x and also deleting variable, not property, return false
<强> BUT 强>
window.x = 5;//add property
delete window.x; // can delete property, return true
和强>
window.x = 5;//add property
delete x; //resolve x. it's a propery of window, return true
及更早
在ECMAScript 262/3中,因为@Peter解释可用DontDelete
标志。但在ECMAScript 262/5.1严格模式下,删除受Configurable
标志:
在严格模式代码中发生删除操作符时,出现SyntaxError 如果其UnaryExpression是对a的直接引用,则抛出异常 变量,函数参数或函数名称。另外,如果一个 删除操作符发生在严格模式代码和属性中 deleted具有属性{[[Configurable]]:false},一个TypeError 抛出异常。
答案 2 :(得分:1)
这就是我理解的:
在全局范围内声明的 var x = 5;
会创建新的window
属性x
。
window.x = 5;
声明(whereever)也会创建新的窗口属性x
。这就是window.x === x
为您提供true
的原因。
不同之处在于,javascript默认根据(上面两个中的一个)的方式为x
属性设置不同的描述符。
var x = 5
等于:
Object.defineProperty(window,'x',{
value: 5,
writable: true,
enumerable: true,
configurable: false
});
而window.x = 5
等于:
Object.defineProperty(window,'x',{
value: 5,
writable: true,
enumerable: true,
configurable: true
});
configurable
描述符(如果false
)禁止delete
该属性。
我们可以假设,当我们使用Object.defineProperty
关键字以简单的方式声明变量或没有(自动分配给var
)时,javascript使用window
具有不同的描述符设置。 。
您只需检查:
var x = 5;
window.y = 5;
console.log(Object.getOwnPropertyDescriptor(window,'x')); //configurable:false
console.log(Object.getOwnPropertyDescriptor(window,'y')); //configurable:true