15

操作员从对象中delete删除属性。如果我在 上设置一个属性window,我可以删除它:

window.myProp = 10;
delete window.myProp;

正如我经常提到的其他人提到的关于操作符状态的行为的文章delete一样,这是因为属性赋值不会设置DontDelete属性(与变量声明相反,它会设置属性)。

该文章还指出以下内容(强调):

请注意,属性是在属性创建期间确定的(即没有设置任何属性)。以后的分配不会修改现有 property 的属性。了解这种区别很重要。

考虑到这一点,为什么我可以覆盖 window, 的现有属性,alert然后将其删除以返回原始值?我错过了一些明显的东西吗?我很少使用delete运算符,所以很可能就是这种情况。

例如:

window.alert = function() {};
alert("Hi!"); //Nothing happens

delete window.alert;
alert("Hello?"); //Alerts 'Hello?'

这是一个证明这一点的小提琴(仅在 Chome 中测试过,很确定 IE 不会以这种方式运行,但现在除了 Chrome 之外无法访问任何东西)。

4

2 回答 2

9

在 Chrome 中,window.alert函数是类原型的一部分DOMWindow,它不是window自身的属性。

因此,当您覆盖时,window.alert您正在向 中添加属性window,但原型中的版本继续存在,但被隐藏了。

当您delete window.alert重新公开原型中的功能时。

下面是一些控制台输出,显示该函数在原型中:

> window.constructor.prototype
DOMWindow

> window.constructor.prototype.alert
function alert() { [native code] }

Firefox 的行为类似,尽管类名不同。

于 2012-04-25T16:19:05.560 回答
2

这是预期的行为,称为阴影。它允许您提供自定义功能而不会消除超类的功能。当您删除该方法时,您的自定义方法将被删除,从原型中显示原始方法。

你越深入继承和理解原型的工作方式,你就会越多地发现自己看到人们这样做的例子。

很好的问题。根据我的经验,这不是大多数 JavaScript 开发人员经常探索的领域。如果不是这种类型的东西,许多扩展或覆盖 JavaScript 基础对象的核心功能的 polyfill 是不可能的。

于 2012-04-25T16:19:24.473 回答