function foobar() {}
console.log(typeof window.foobar); // "function"
console.log(typeof window.alert); // "function"
delete window.foobar;
delete window.alert;
console.log(typeof window.foobar); // "function"
console.log(typeof window.alert); // "undefined"
console.log(window.hasOwnProperty('foobar')); // true
console.log(window.hasOwnProperty('alert')); // false
有人可以解释一下,这怎么可能?
为什么不能简单地删除foobar
window对象的属性?
为什么像foobar
操作程序这样的自定义全局函数受到保护,而delete
操作程序却没有这样的内置全局函数alert
?
全局变量不可配置:
Object.getOwnPropertyDescriptor(window, 'foobar').configurable; // false
这是因为根据静态语义:TopLevelVarDeclaredNames,函数声明就像var
声明:
在函数或脚本的顶层,内部函数声明被视为var声明。
而运行时语义:GlobalDeclarationInstantiation则将它们声明为不可配置的:
- 对于每一个生产˚F在functionsToInitialize,做
- 让status为envRec。CreateGlobalFunctionBinding(fn,fo,false)。
CreateGlobalFunctionBinding(N,V,D)使用参数false作为属性的可配置性:
- 设desc为PropertyDescriptor {[[Value]]:V,[[Writable]]:true,[[Enumerable]]:true,[[Configurable]]:D }。
因此,操作员使用的[[Delete]]内部方法不会成功:delete
如果desc。[[Configurable]]为true,则
- 从O中删除名称为P的自有属性。
- 返回true。
返回false。
这就是为什么您应该使用严格模式。否则,某些问题将被忽略。
delete window.foobar; // false (in sloppy mode)
delete window.foobar; // TypeError (in strict mode)
您可以删除本机,alert
因为它是可配置的。
HTML规范中将该方法定义为IDL方法:
[Global] /*sealed*/ interface Window : EventTarget { // ... void alert(optional DOMString message = ""); };
根据WebIDL的规定,如果公开的操作不是不可伪造的,则它们应该是可配置的:
该属性具有属性{[[[Writable]]:B,[[Enumerable]]:true,[[Configurable]]:B },如果操作在接口上不可伪造,则B为false,否则为true。
Object.getOwnPropertyDescriptor(window, 'alert').configurable; // true
如果要删除该函数,请将其分配为属性,而不要使用函数声明:
window.foobar = function() {};
Object.getOwnPropertyDescriptor(window, 'foobar').configurable; // true
delete window.foobar; // true
这是因为通过属性分配创建属性时,它是可配置的。从[[Set]]内部方法使用的CreateDataProperty中,
- 令newDesc为PropertyDescriptor {[[Value]]:V,[[Writable]]:true,[[Enumerable]]:true,[[Configurable]]:true }。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句