JavaScript全局对象详解:ECMAScript核心对象与宿主环境对象的差异

作者:拾光

时间:2026-10-27

浏览:458

本文深入解析JavaScript中两类全局对象:ECMAScript规范定义的内置对象(如NaN、eval、Object)与宿主环境提供的对象(如window、document)。通过代码测试对比两者在可写性、可枚举性及不同浏览器(IE、Firefox、Chrome等)中的行为差异,揭示直接赋值与var声明在全局作用域下的底层实现区别。

文章目录

JavaScript全局对象分类概述

本文讨论的JavaScript环境涵盖浏览器及其宿主环境。全局对象与函数主要分为两类:一是ECMAScript规范定义的全局对象(Global Object),二是宿主环境(Host)提供的全局对象与函数。

ECMAScript核心内置对象特性

一、ECMAScript核心内置对象

这类对象由ECMAScript标准定义,不依赖具体宿主环境,在程序执行前已实例化存在。ECMAScript规范将其称为The Global Object,具体包含以下几类属性。

1. 值属性(Value Properties):包括NaN、Infinity和undefined。 2. 函数属性(Function Properties):包括eval、parseInt、parseFloat、isNaN、isFinite、decodeURI、encodeURI、encodeURIComponent等。 3. 构造器(Constructor)属性:包括Object、Function、Array、String、Boolean、Number、Date、RegExp、Error以及各类错误构造器(EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError)。 4. 其他属性(Other Properties):类似于Java中的静态类,可直接通过类名调用方法,包括Math和JSON。

ECMAScript规范指出,这些标准内置全局对象属性具有Writable为true、Enumerable为false、Configurable为true的特性。这意味着它们可以被重写,但不能通过for...in循环枚举。规范原文如下。

Unless otherwise specified, the standard built-in properties of the global object have attributes {[[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}.

尽管规范允许重写这些全局对象,但实际开发中极少有人这样做。此处仅进行简单测试以验证其行为。

测试代码如下:

NaN = 11;
eval = 22;
Object = 33;
Math = 44;
alert(NaN);
alert(eval);
alert(Object);
alert(Math);<BR>

上述代码分别对值属性(NaN)、函数属性(eval)、构造器属性(Object)及其他属性(Math)进行重写赋值。观察结果如下:

JavaScript全局对象分类概述

结果显示,除NaN在IE9(pre3版本)和Safari中无法被重写外,其他全局对象均成功被重写。此处仅列举四项,读者可自行测试所有The Global Object。核心结论是:ECMAScript内置全局对象通常可被重写,尽管这并非推荐做法。

接下来测试这些全局对象的可枚举性。

测试代码如下:

for(var a in NaN){
alert(a);
} 
for(var a in eval){
alert(a);
} 
for(var a in Object){
alert(a);
} 
for(var a in Math){
alert(a);
} 

所有主流浏览器均未弹出提示框,表明这些全局对象属性不可枚举。读者可自行测试其他The Global Object。值得注意的是,在Firefox等浏览器中,若全局对象被重写,其可枚举性可能会发生变化。

宿主环境全局对象的重写行为

二、宿主环境提供的全局对象/函数

此类对象由宿主环境(如浏览器)提供,包括window、alert、setTimeout、document、location等。多数浏览器对其重写行为有限制。

测试代码如下:

window = 55;
alert(window);

在IE浏览器中,执行window = 55会报错“非法复制”,后续alert未执行。而在其他浏览器中,该赋值语句无效,window仍保持原值并正常弹出。

进一步测试重写alert函数。

测试代码如下:

alert = 55;
console.log(alert);

IE浏览器报错,而Firefox、Chrome、Safari和Opera均允许重写,控制台输出55。这表明:对于宿主环境提供的全局对象,部分浏览器禁止重写,部分则允许。

全局变量声明的浏览器内部实现差异

以下探讨两种声明全局变量的方式及其内部实现差异。

测试代码如下:

a1 = 11;
var a2 = 22;
for(a in window){
if(a=='a1'||a=='a2'){
alert(a)
    } 
} 

在IE浏览器中,上述代码不会弹出提示框。其内部机制大致如下:


模拟IE内部实现:

//IE
with(host_object){//window
with(global_object){//Global
a1 = 11;
var a2 = 22;
    }    
} 

即a1和a2作为第一种全局对象(JS引擎提供的Global对象)的属性,而非第二种宿主环境提供的window对象的属性。因此,在IE中执行for...in window时,a1和a2均不可见。若IE提供Global对象的引用,以下代码或许能弹出提示框。


测试代码如下:

for(a in Global){
if(a=='a1'||a=='a2'){
alert(a)
    } 
} 

在Firefox、Safari、Chrome和Opera中,内部机制大致如下:


模拟其他浏览器内部实现:

//Firefox/Safari/Chrome/Opera
with(host_object){//window
a1 = 11;
var a2 = 22;
with(global_object){//Global
    }    
} 

即a1和a2作为第二种全局对象(宿主环境提供的window对象)的属性。因此,在for...in window时,a1和a2均存在,提示框正常弹出。

第三种声明全局变量的方式是显式将变量挂载到window对象上,如window.a3 = 33。这种方式在所有浏览器中执行for...in window时均可获取到a3。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章