RefereceType与this指向

引用类型(Reference Type)

这个过程是用来模拟js引擎内部工作机制,并不是真正代码实现。
简介:
此引用类型不是数据的引用类型,而是一种规范类型,他主要是一个指代,代替一个标识符或属性的表示方式,你可以将引用类型就看成是一个标识符的一种表示方式,保存了标识符的一些信息,需要真实值时又可以通过它找到真实值。

注: 标识符就是变量名,函数名,函数参数名和全局对象中未识别的属性名

我们用伪代码的形式来表示引用类型的结构,看成是拥有两个属性的对象:

  1. 属性base,即标识符所属的那个对象
  2. 标识符名(或者叫属性名)
var valueOfReferenceType = {
    base: <base object>,
    propertyName: <property name>
};

引用类型的使用情景有二

  1. 当我们处理一个标识符时会返回引用类型
  2. 在处理一个属性访问器时会返回引用类型

在该过程中,总是返回一个引用类型的值

示列

var foo = 10;
function bar(){}

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

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

在js中所有标识符都有所属对象,在执行环境中有个变量对象来保存环境中的标识符。

所以引用类型的base:
在全局上下文中,毋庸置疑,base === globalVO === gloabal
在函数的执行上下文中,base === VO/AO

但处理对象属性是:
这个更是简单,base === owerObject

用类型只是一个指代,它并不保存真正的值。当需要真正的值时,可以通过内部一系列算法,可以得到。这个算法,我们可以用简单的伪代码来描述:

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"

我们获取引用类型的值时,一般是进行赋值、参与运算、或调用时都会触发GetValue获取真正值。

注意: 通过GetValue获取到的值不再是引用类型

访问属性有两种语法: 以点(.)语法或者括号语法([])

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

在中间计算的引用类型的值为:

var fooBarReference = {
  base: foo,
  propertyName: 'bar'
};
 
GetValue(fooBarReference); // function object "bar"

一个函数中确定this值的通用规则如下:
在一个函数上下文中,this由调用者提供,由函数的调用方式来决定。如果调用括号()的左边是引用类型的值,this指向引用值的base对象(baseObject),在不适引用类型的情况下,值为null。不过,实际不存在this值为null的情况下,因为this值为null时,其值会被隐式转换成全局对象。注:ES5中,已经不强迫转换成全局对象了,而是赋值undefined。

我们看看例子中的表现:
(1) 调用括号左边是引用类型的值
this指向base,找到base即可。如果是全局变量下申明的,那就指向全局对象。

var myObject = {
     foo : function(){
            console.log(this);
      } 
}
myObject.foo(); //毫无疑问,这个foo的base是myObject,故foo方法中的this指向myObject。

同样,使用属性访问器:this也指向base

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

但是以另一种形式调用函数,我们得到其他的this值

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

因为test作为global的属性,因此生成的引用类型不和上面一样,其base所属对象是global

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

(2)调用括号左边是引用类型的值,不过这个值为null

function myFunction() {
     var foo = function(){
            console.log(this);
      } 
       foo();    //AO.foo() => null.foo()
}
myFunction(); //输出:Window {top: Window, window: Window...}

当一个内部函数被调用时,这个内部函数的base应该是当前执行上下文中活动对象(AO),但是在javascript内部在AO作为base时,都当做null处理,javascript当然不允许this为null的情况发生,所有就将base设置为global对象(这是前文this函数调用模式中设计错误的源头)。所以在这情况下,this都指向全局对象。

(3)调用括号左边不是引用类型的值

//简单点的例子
(function () {
  console.log(this); // null => global
})();
//复杂些的例子
var foo = {
  bar: function () {
    console.log(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自动设置为null,结果为全局对象

第一个例子中,立即函数,它的函数调用小括号左边是一个表达式,不是一个引用。

第二个例子复杂了许多,我们来一个个分析:

foo.bar(),这个没有疑问,base为foo,this指向foo。

(foo.bar)(),这里用到了一个小括号,它在这起到分组符作用,也就是它不会迫使引用类型执行GetValue方法,其执行结果,跟上面一模一样。

后面三个,小括号里面依次是赋值运算、或运算和逗号运算,它们都会迫使引用类型执行GetValue方法,从而返回一个函数对象。这样,函数调用小括号左边就不再是引用类型了,所有,this都是指向全局对象的

转载于:
https://www.jb51.net/article/44576.htm
https://www.cnblogs.com/TomXu/archive/2012/01/17/2310479.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值