为何window.eval()可正常执行,但eval未作为Window对象的属性被枚举出来?
为何window.eval()可正常执行,但eval未作为Window对象的属性被枚举出来?
问题描述
I noticed that the
eval()function in JavaScript is not listed as a property of theWindowobject, although it is still accessible by callingwindow.eval(). Why is this?
用户用于测试的代码如下:
JavaScript代码
listKeys(document.getElementById("container"), globalThis); function listKeys(elem, obj){ const keys = Object.keys(obj); keys.sort(); let html = `Properties on <b>${obj}</b>:<br/>`; let i = 0; keys.forEach(key=>{ if(key === "localStorage" || key === "sessionStorage"){ return; } html+=`<br/>${++i}. `+key+(typeof obj[key] === "function" ? `()`:``); }); elem.innerHTML = html; }
HTML代码
<!doctype html> <html> <head> <style> body{ font-size:14px; background-color:beige; font-family:'Segoe UI','Lucida Grande',-apple-system,BlinkMacSystemFont,'Liberation Sans',sans-serif; } </style> </head> <body> <div id="container"></div> </body> </html>
回答
这个问题问得很戳点!其实核心原因是eval是Window对象的不可枚举自有属性——它确实属于Window,但被语言标准标记为不可枚举,所以用Object.keys()这类只遍历可枚举属性的方法找不到它,但直接通过window.eval()调用完全没问题。
具体拆解一下:
- 不可枚举的属性特性:
Object.keys()只会返回对象自身的「可枚举属性」,而eval在Window上的属性描述符里,enumerable字段被设置为false。你可以在浏览器控制台验证这一点:
输出结果里会明确显示console.log(Object.getOwnPropertyDescriptor(window, 'eval'));enumerable: false,这就是你的listKeys函数遍历不到它的原因。 - 不可枚举≠不存在:不可枚举只是让它不会出现在常规的枚举遍历中,并不代表这个属性不存在。就像Window上还有不少类似的属性(比如
window.location也是不可枚举的访问器属性),你照样能通过点语法直接访问和调用。 - 如何看到它:如果想要列出Window的所有自有属性(包括不可枚举的),只需要把代码里的
Object.keys(obj)替换成Object.getOwnPropertyNames(obj),这样就能在输出结果里找到eval了。
根据ECMAScript规范,eval作为全局对象(浏览器环境下即Window)的自有属性,天生就带有[[Enumerable]]: false的特性,这是语言标准的规定,主要是为了避免这个行为特殊的函数被意外遍历到——毕竟eval的使用场景很有限,而且滥用会带来安全和性能问题。
备注:内容来源于stack exchange,提问作者user3163495
相关产品推荐
相关产品推荐

