浅谈关于JavaScript的语言特性分析(2)

变量对象在函数执行上下文中,VO(variable object)是不能直接访问的,此时由活动对象(activation object)扮演VO的角色。 活动对象是在进入函数上下文时刻被创建的,它通过函数的arguments属性初始化。arguments属性的值是Arguments对象:


复制代码 代码如下:


function foo(x, y, z) {
  // 声明的函数参数数量arguments (x, y, z)
  alert(foo.length); // 3
  // 真正传进来的参数个数(only x, y)
  alert(arguments.length); // 2
  // 参数的callee是函数自身
  alert(arguments.callee === foo); // true
}

当进入执行上下文(代码执行之前)时,VO里已经包含了下列属性:1. 函数的所有形参(如果我们是在函数执行上下文中);

•所有函数声明(FunctionDeclaration, FD);
•所有变量声明(var, VariableDeclaration);
另一个经典例子:

复制代码 代码如下:


alert(x); // function
var x = 10;
alert(x); // 10
x = 20;
function x() {};
alert(x); // 20

根据规范函数声明是在当进入上下文时填入的; 在进入上下文的时候还有一个变量声明“x”,那么正如我们在上面所说,变量声明在顺序上跟在函数声明和形式参数声明之后,而且在这个进入上下文阶段,变量声明不会干扰VO中已经存在的同名函数声明或形式参数声明。变量相对于简单属性来说,变量有一个特性(attribute):{DontDelete},这个特性的含义就是不能用delete操作符直接删除变量属性。

复制代码 代码如下:


a = 10;
alert(window.a); // 10
alert(delete a); // true
alert(window.a); // undefined
var b = 20;
alert(window.b); // 20
alert(delete b); // false
alert(window.b); // still 20。b is variable,not property!
var a = 10; // 全局上下文中的变量
(function () {
  var b = 20; // function上下文中的局部变量
})();
alert(a); // 10
alert(b); // 全局变量 "b" 没有声明.

this在一个函数上下文中,this由调用者提供,由调用函数的方式来决定。如果调用括号()的左边是引用类型的值,this将设为引用类型值 的base对象(base object),在其他情况下(与引用类型不同的任何其它属性),这个值为null。不过,实际不存在this的值为null的情况,因为当this的值 为null的时候,其值会被隐式转换为全局对象。

复制代码 代码如下:


(function () {
  alert(this); // null => global
})();<SPAN>&nbsp;</SPAN>

在这个例子中,我们有一个函数对象但不是引用类型的对象(它不是标示符,也不是属性访问器),相应地,this值最终设为全局对象。

复制代码 代码如下:


var foo = {
    bar: function () {
      alert(this);
    }
};
foo.bar(); // Reference, OK => foo
(foo.bar)(); // Reference, OK => foo
(foo.bar = foo.bar)(); // global
(false || foo.bar)(); // global
(foo.bar, foo.bar)(); // global

问题在于后面的三个调用,在应用一定的运算操作之后,在调用括号的左边的值不在是引用类型。

•第一个例子很明显———明显的引用类型,结果是,this为base对象,即foo。

•在第二个例子中,组运算符并不适用,想想上面提到的,从引用类型中获得一个对象真正的值的方法,如GetValue。相应的,在组运算的返回中———我们得到仍是一个引用类型。这就是this值为什么再次设为base对象,即foo。

•第三个例子中,与组运算符不同,赋值运算符调用了GetValue方法。返回的结果是函数对象(但不是引用类型),这意味着this设为null,结果是global对象。

•第四个和第五个也是一样——逗号运算符和逻辑运算符(OR)调用了GetValue 方法,相应地,我们失去了引用而得到了函数。并再次设为global。

正如我们知道的,局部变量、内部函数、形式参数储存在给定函数的激活对象中。

复制代码 代码如下:


function foo() {
   function bar() {
      alert(this); // global
   }
   bar(); // the same as AO.bar()
}

活动对象总是作为this返回,值为null——(即伪代码的AO.bar()相当于null.bar())。这里我们再次回到上面描述的例子,this设置为全局对象。


作用域链

通过函构造函数创建的函数的scope属性总是唯一的全局对象。

一个重要的例外,它涉及到通过函数构造函数创建的函数。

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdgsjf.html