JavaScript中的window对象的getter/setter方法

4
为什么在Firefox 21.0中以下代码会抛出TypeError?
Object.defineProperty(window,'windowProperty',{
    get: function(){
        return 'windowProperty'
    },

    set: function(val){
        console.log('windowProperty is being set');
    },

    configurable: true,
});

var windowProperty;

但是不使用 var 声明 windowProperty 也可以:
windowProperty;

或者

window.windowProperty;

这种行为在spidermonkey中也存在:
var a=1;

Object.defineProperty(this,'a',{
    get: function(){
        return 'a';
    },
});

你在用哪个浏览器?我在Chrome和Firefox上尝试了一下,没有看到TypeError。 - mohkhan
在IE中一切都正常工作。你有什么问题吗? - c69
更新,我的问题不是针对IE而是针对Firefox。 - simonzack
1个回答

2

仅写作

windowProperty;

该代码并未声明变量,它只是尝试在最接近的上下文中返回变量内容,如果找不到则返回undefined。这就像没有目标的赋值一样。例如,您也可以编写随机文本而不会引发错误:

'Hello, world !';
123456;
undefined;

使用var关键字来定义已经在代码中定义过的属性,这样会导致错误。不要尝试重新定义已经存在的属性。

编辑
正如simonzack所指出的那样,当重新定义变量时,浏览器并不总是发送错误信息。例如:

var test; var test;

即使这样做是不好的想法,一些JS验证器会警告你,但不会抛出错误。然而,通过定义getter和setter,浏览器会“锁定”该属性(例如,防止在同一属性上使用两个不同的setter引起冲突)。

我的错,我误解了。

你重新定义变量的原因是什么?

编辑2
考虑到var声明在defineProperty之前,它可以对我的解释进行精确说明。事实上,当您首次使用var声明时,浏览器将其configurable状态设置为false,这会阻止对其描述符进行更改(请参见链接)。因此,当您尝试使用defineProperty函数更改它时,会导致错误。更好地理解的一个例子是将代码包装在闭包函数中。这样,由var定义的windowProperty不是同一个,一切都很好。

(function () {
    var windowProperty;
    Object.defineProperty(...);
    //It works because the previously defined variable is in the scope of the function and thus is not the same as window.windowProperty.
})();

根据你的逻辑,var test;var test; 应该会抛出一个错误,实际上并没有。 - simonzack
@simonzack 你是正确的,我回答的第二部分是不完整的。那是因为你定义了这个属性的访问器(getset),所以浏览器会将其'锁定'。我会更新我的回答。 - Bali Balo
浏览器实际上只有在configurable设置为false时才会“锁定”属性。请查看Mozilla文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty。这与“var”有什么关系? - simonzack
我这么做是因为在这种情况下,我不确定为什么它的行为与window.windowProperty不同。而且你的回答并没有解释getter/setter中“重新定义”的含义。你能给我提供文档的参考吗?我找不到任何相关的资料。顺便说一下,var windowProperty实际上是在defineProperty之前运行的,我想你可能没有意识到这一点。 - simonzack
不,我不知道 var 是在 defineProperty 之前出现的(你问题中的代码颠倒了,请更新以避免混淆)。 考虑到这一点,我认为你的问题是初始化属性时自动将其 configurable 设置为 false(默认值),因此无法更改它:http://tinyurl.com/n4jxyd4 在 configurable 设置为 false 时不覆盖 getter 和 setter 的原因在你之前提供的链接中给出:http://tinyurl.com/kuumtk9。 - Bali Balo
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接