JavaScript 中this的实现原理

 

 

学懂 JavaScript 言语,一个标志就是了解下面两种写法,或许有不一样的成果。

<blockquote "="">

var obj = { foo: function () {} }; var foo = obj.foo;  // 写法一 obj.foo()  // 写法二 foo() 

上面代码中,尽管obj.foo和foo指向同一个函数,可是履行成果或许不一样。请看下面的比如。

<blockquote "="">

var obj = { foo: function () { console.log(this.bar) }, bar: 1 }; var foo = obj.foo; var bar = 2; obj.foo() // 1 foo() // 2 

这种差异的原因,就在于函数体内部使用了this关键字。许多教科书会通知你,this指的是函数运转时地点的环境。关于obj.foo()来说,foo运转在obj环境,所以this指向obj;关于foo()来说,foo运转在大局环境,所以this指向大局环境。所以,两者的运转成果不一样。

这种解释没错,可是教科书往往不通知你,为什么会这样?也就是说,函数的运转环境到底是怎么决议的?举例来说,为什么obj.foo()就是在obj环境履行,而一旦var foo = obj.foo,foo()就变成在大局环境履行?

本文就来解释 JavaScript 这样处理的原理。了解了这一点,你就会完全了解this的效果。

二、内存的数据结构

JavaScript 言语之所以有this的规划,跟内存里边的数据结构有关系。

<blockquote "="">

var obj = { foo: 5 }; 

上面的代码将一个目标赋值给变量obj。JavaScript 引擎会先在内存里边,生成一个目标{ foo: 5 },然后把这个目标的内存地址赋值给变量obj。

也就是说,变量obj是一个地址(reference)。后面如果要读取obj.foo,引擎先从obj拿到内存地址,然后再从该地址读出原始的目标,返回它的foo特点。

原始的目标以字典结构保存,每一个特点名都对应一个特点描绘目标。举例来说,上面比如的foo特点,实际上是以下面的方式保存的。

<blockquote "="">

{ foo: { [[value]]: 5 [[writable]]: true [[enumerable]]: true [[configurable]]: true } } 

留意,foo特点的值保存在特点描绘目标的value特点里边。

三、函数

这样的结构是很明晰的,问题在于特点的值或许是一个函数。

<blockquote "="">

var obj = { foo: function () {} }; 

这时,引擎会将函数独自保存在内存中,然后再将函数的地址赋值给foo特点的value特点。

<blockquote "="">

{ foo: { [[value]]: 函数的地址 ... } } 

因为函数是一个独自的值,所以它可以在不同的环境(上下文)履行。

<blockquote "="">

var f = function () {}; var obj = { f: f };  // 独自履行 f()  // obj 环境履行 obj.f() 

四、环境变量

JavaScript 允许在函数体内部,引用当时环境的其他变量。

<blockquote "="">

var f = function () { console.log(x); }; 

上面代码中,函数体里边使用了变量x。该变量由运转环境提供。

现在问题就来了,因为函数可以在不同的运转环境履行,所以需要有一种机制,http://www.qijihu.com专卖网站可以在函数体内部获得当时的运转环境(context)。所以,this就呈现了,它的规划意图就是在函数体内部,指代函数当时的运转环境。

<blockquote "="">

var f = function () { console.log(this.x); } 

上面代码中,函数体里边的this.x就是指当时运转环境的x。

<blockquote "="">

var f = function () { console.log(this.x); } var x = 1; var obj = { f: f, x: 2, };  // 独自履行 f() // 1  // obj 环境履行 obj.f() // 2 

上面代码中,函数f在大局环境履行,this.x指向大局环境的x。

在obj环境履行,this.x指向obj.x。

回到本文开头提出的问题,obj.foo()是经过obj找到foo,所以就是在obj环境履行。一旦var foo = obj.foo,变量foo就直接指向函数自身,所以foo()就变成在大局环境履行。

(完)

 

转载于:https://www.cnblogs.com/blogst/p/10319155.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值