JavaScript中的this

54 阅读2分钟

road-asphalt-space-sky-56832.jpeg

下面的两种写法,结果有何不同?

问题

虽然obj.foofoo指向同一个函数,但是执行结果可能不同。例如

eg

产生这种差异的原因,在于函数内部使用了this关键字。根据书面解释这种情况:this指的是函数运行时的环境。也就是对于obj.foo()来说,foo运行在obj环境;foo运行在全局环境,所以两者运行结果不一样。

思考

  • 函数的运行环境到底怎么决定?
  • var foo = obj.foo 为什么赋值后foo就成了全局执行环境?

内存的数据结构

var obj = { foo : 5 };

上面的代码将一个对象赋值给变量obj。JavaScript会先内存里面生成一个对象{foo:5},然后再把内存地址赋值给变量obj。也就是obj是一个地址。

对象的的每一个属性,实际是以字典结构的形式保存的,类似下图, 对象的每个属性都包含描述属性。其中value属性保存对应的值。

bg2018061802.png

思考

如果属性的值是函数或者其他引用类型。描述属性中的value应该是什么,例如

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

这时,JavaScript引擎会把函数单独保存在内存中,然后把地址赋值给value属性

bg2018061803.png

由于函数是一个单独的值,所以可以在不同的环境(上下文)中执行。

环境变量

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

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

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

现在问题就来了,由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。

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

上面代码中,函数体里面的this.x就是指当前运行环境的x

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

bg2018061804.pngobj环境执行,this.x指向obj.x

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

原文地址