felix-cao / Blog

A little progress a day makes you a big success!
31 stars 4 forks source link

JavaScript变量对象(Variable Object简称VO) #57

Open felix-cao opened 6 years ago

felix-cao commented 6 years ago

  在编码的时候,我们会定义变量、封装函数来构造我们的系统。那么 JavaScript 引擎是如何找到这些数据的(变量和函数)呢?

   我们知道变量和所处的执行上下文是有密切关系的

var a=10;  // 全局上下文环境下的变量
(function(){
    var b=20; // 函数上下文环境下的局部变量
})();
alert(a); // 10
alert(b); // "b" 未定义

  在上篇 JavaScript执行上下文栈(Execution Context Stack简称ECS) #58 中,浏览器执行一段 JavaScript 可执行代码(Executable code)时,会创建对应的执行上下文,执行上下文在创建阶段会创建变量对象,建立作用域链,以及确定this的指向。 也就是说对于每一个执行上下文,都有三个重要属性:

本篇主要聊一聊变量对象。

  变量对象是与执行上下文相关的数据作用域,存储了在上下文中定义的变量和函数声明。不同的执行上下文下的变量对象稍有不同,所以我们来聊聊全局上下文下的变量对象和函数上下文下的变量对象。

全局对象

  在W3school中,关于全局对象的描述是这样的:

  全局对象是预定义的对象,作为 JavaScript 的全局函数和全局属性的占位符。通过使用全局对象,可以访问所有其他所有预定义的对象、函数和属性。全局对象不是任何对象的属性,所以它没有名称。   在顶层 JavaScript 代码中,可以用关键字 this 引用全局对象。但通常不必用这种方式引用全局对象,因为全局对象是作用域链的头,这意味着所有非限定性的变量和函数名都会作为该对象的属性来查询。例如,当JavaScript 代码引用 parseInt() 函数时,它引用的是全局对象的 parseInt 属性。全局对象是作用域链的头,还意味着在顶层 JavaScript 代码中声明的所有变量都将成为全局对象的属性。   全局对象只是一个对象,而不是类。既没有构造函数,也无法实例化一个新的全局对象。

  对于任何JavaScript程序,当程序开始运行时,JavaScript解释器都会初始化一个全局对象以供程序使用。这个JavaScript自身提供的全局对象的功能包括:

1.全局对象拥有一些常用的属性值。比如undefined、Infinity以及NaN。 2.全局对象拥有一些常用的属性对象。比如Math、JSON和Number对象均为该全局对象的属性。 3.全局对象提供一些全局函数供调用。比如isNaN()、isFinite()、parseInt()和eval()等。 4.全局对象提供一些全局构造器(constructor),也即全局类。比如Date()、RegExp()、String()、Object()和Array()等。

除了JS全局对象,对于运行在浏览器端的JavaScript程序,还有另一个全局对象:window。window全局对象提供了与当前窗口、页面有关的诸多属性与方法。除了这些与浏览器有关的全局属性和方法,window对象还封装了JS全局对象,并向外暴露JS全局对象的属性与接口;因此,当进行浏览器端JavaScript编程时,只需关心window全局对象即可。

对于JavaScript程序中的this,如果this不属于任何function,那么这个this就指代JS全局对象;如果是浏览器端运行的JS程序,那么这个this就指代window全局对象。

如果这个this属于某个function,那么this指代的就是调用该function的对象。若这种情况下function只是一个普通的函数,而不是某个类的方法,那么this的指代存在两种可能:

1.在ECMAScript 3标准,以及ECMAScript 5标准的非严格模式下,this指代全局对象。 2.在ECMAScript 5标准的严格模式下,this指代undefined。

Reference

ECMA-262-3 in detail. Chapter 2. Variable object.