深入理解JavaScript系列(13) This? Yes,this!(2)


var valueOfReferenceType = {
base: <base object>,
propertyName: <property name>
};


引用类型的值只有两种情况:

当我们处理一个标示符时
或一个属性访问器
标示符的处理过程在下一篇文章里详细讨论,在这里我们只需要知道,在该算法的返回值中,总是一个引用类型的值(这对this来说很重要)。

标识符是变量名,函数名,函数参数名和全局对象中未识别的属性名。例如,下面标识符的值:

复制代码 代码如下:


var foo = 10;
function bar() {}


在操作的中间结果中,引用类型对应的值如下:

复制代码 代码如下:


var fooReference = {
base: global,
propertyName: 'foo'
};

var barReference = {
base: global,
propertyName: 'bar'
};


为了从引用类型中得到一个对象真正的值,伪代码中的GetValue方法可以做如下描述:

复制代码 代码如下:


function GetValue(value) {

if (Type(value) != Reference) {
return value;
}

var base = GetBase(value);

if (base === null) {
throw new ReferenceError;
}

return base.[[Get]](GetPropertyName(value));

}


内部的[[Get]]方法返回对象属性真正的值,包括对原型链中继承的属性分析。

复制代码 代码如下:


GetValue(fooReference); // 10
GetValue(barReference); // function object "bar"


属性访问器都应该熟悉。它有两种变体:点(.)语法(此时属性名是正确的标示符,且事先知道),或括号语法([])。

复制代码 代码如下:


foo.bar();
foo['bar']();


在中间计算的返回值中,我们有了引用类型的值。

复制代码 代码如下:


var fooBarReference = {
base: foo,
propertyName: 'bar'
};

GetValue(fooBarReference); // function object "bar"


引用类型的值与函数上下文中的this值如何相关?——从最重要的意义上来说。 这个关联的过程是这篇文章的核心。 一个函数上下文中确定this值的通用规则如下:

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

我们看看这个例子中的表现:

复制代码 代码如下:


function foo() {
return this;
}

foo(); // global


我们看到在调用括号的左边是一个引用类型值(因为foo是一个标示符)。

复制代码 代码如下:


var fooReference = {
base: global,
propertyName: 'foo'
};


相应地,this也设置为引用类型的base对象。即全局对象。

同样,使用属性访问器:

复制代码 代码如下:


var foo = {
bar: function () {
return this;
}
};

foo.bar(); // foo


我们再次拥有一个引用类型,其base是foo对象,在函数bar激活时用作this。

复制代码 代码如下:


var fooBarReference = {
base: foo,
propertyName: 'bar'
};


但是,用另外一种形式激活相同的函数,我们得到其它的this值。

复制代码 代码如下:


var test = foo.bar;
test(); // global


因为test作为标示符,生成了引用类型的其他值,其base(全局对象)用作this 值。

复制代码 代码如下:


var testReference = {
base: global,
propertyName: 'test'
};


现在,我们可以很明确的告诉你,为什么用表达式的不同形式激活同一个函数会不同的this值,答案在于引用类型(type Reference)不同的中间值。

复制代码 代码如下:

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

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