【问题标题】:Non property assigned variable is delete-able非属性分配变量是可删除的
【发布时间】:2012-10-24 02:19:24
【问题描述】:

我正在阅读 Javascript delete 方法上的 this article,并尝试了以下代码:

function f(){
    var x = "abcd";
    console.log(delete x); //returns false, because x has DontDelete attribute
    y = "abcd";
    console.log(delete y); //returns true, but I didn't explicitly assign y as a property
}

这很奇怪,因为我没有使用y 的属性分配(如:window.y="abcd";),文章claims 是您如何创建属性deleteable。

为什么y 没有DontDelete 属性?

更新:

在下面的答案中,声称 y 是可删除的,仅仅是因为它是 window 对象的属性。那不是真的。考虑以下 sn-p:

function f() {
    var functionx = "abcd";
    console.log(delete functionx); //returns false, because x has DontDelete attribute
    functiony = "abcd";
    console.log(delete functiony); //returns true, but I didn't explicitly assign functiony as a property to the window
}

//take 1
var globalx = "abcd";
console.log(this.globalx);//to prove x is a property of the global
console.log(delete globalx);//fails, even though x is a property of the window

//take 2
this.globaly = "abcd";
console.log(this.globaly);//to prove y is a property of the global
console.log(delete globaly);//succeeds, because I used property assignment

f();

在 take 1 中,globalx 是窗口的一个属性,但它仍然是不可删除的。 delete 是否成功的标准不是变量是否是某物的属性(始终为真),而是该属性是否具有DontDelete 属性集。

【问题讨论】:

  • 当我run the edited code 时,我当然不会得到你描述的结果。我认为给出的答案仍然有效。
  • @KendallFrey 您需要将脚本放在正文中,而不是放在 onLoad 事件中。这是一个更新的小提琴:jsfiddle.net/jpF73/2 另外,我不小心错过了localx 旁边的var

标签: javascript properties attributes


【解决方案1】:

delete x 无效,因为它不解析为任何对象属性。

y 解析为 window 对象的属性。

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/delete:

删除表达式

表达式应该评估为属性引用

【讨论】:

  • x不是当前执行上下文的变量对象的属性吗?
  • @Asad 这是一个实现细节,从 js 的角度来看它只是一个变量。它不是用户态代码可访问的任何对象的属性。
  • 我有点明白了,但是为什么在全局上下文中运行var x="abcd";console.log(delete x); 会记录错误?当我使用var x 时,x 仍然是窗口对象的一个​​属性。为什么无法删除?
  • @Asad 使用var 创建的全局变量具有DontDelete(即configurable === false...如果您使用window.x = "abcd",它应该可以工作。见jsfiddle.net/yeJ2b/1
【解决方案2】:

JavaScript 中的变量are declared using var keyword。当您省略var 时,解释器开始寻找定义给定变量的最近范围。如果没有找到给定的变量,it will be created as a new property on a global object

这正是这里发生的事情:

  • 变量 y 被引用并分配了一个新值 (abcd)
  • Var y 未在任何地方定义 → 创建新的全局属性 y 并为其赋值(实际上是 window.y = "abcd")。
  • 因此,y 成为全局对象的属性,可以删除。

【讨论】:

  • 感谢您的回答。我的问题是并非全局对象的所有属性都可以删除。查看我的更新。
【解决方案3】:

这是第二个例子的扩展版本:

window.y = "abcd";
console.log(delete window.y);

现在发生的事情很明显。

如果不使用var 关键字,解释器会假定变量是全局对象的属性(通常为window),如this JSFiddle 所示。请注意,在全局范围内,thiswindow 对象相同。

回复:更新:

在函数之外,使用var 声明的变量被定义为全局对象的不可配置 属性。这在https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/var 中有详细说明,其中写道:

在函数外部使用var 是可选的;为未声明的变量赋值隐含地将其声明为全局变量(也是全局对象的属性)。区别在于声明的变量是全局对象的不可配置属性,而未声明的变量是可配置的。

在函数内部声明一个变量并不会将其分配给一个全局属性,而是一个局部变量。

这解释了您在全局范围内定义变量时看到的行为。

【讨论】:

  • 不,没有var 会搜索父范围 - 它与this 无关。如果在任何地方都找不到标识符,则认为它是全局对象的全局变量/属性。
  • @Bergi 感谢您指出这一点。我已经更新了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-30
  • 1970-01-01
  • 1970-01-01
  • 2019-12-02
  • 1970-01-01
  • 2022-01-23
  • 2021-09-20
相关资源
最近更新 更多