美文网首页
JS中的this值

JS中的this值

作者: 一许青衫一 | 来源:发表于2019-03-31 13:37 被阅读0次

前言

  看博客文章和别人写的代码时,经常会看到函数调用call(),apply(),bind()方法,因为很少见到函数本身去调用一个方法,所以感到很奇怪,也造成了对这三个方法的理解上的障碍。退后一步,仔细梳理了一下思路,发现了我产生奇怪感觉的来源。那就是函数在我的知识体系里,是作为一个方法的,里面包含了对数据对象的操作。而call,apply,bind等于是方法调用方法,这就让我疑惑了。但是现在看来,这并没有奇怪的。因为主体部分,还是调用的方法。而call,apply和bind是用来完善调用方法的。既然有完善,那就肯定有缺漏的地方,因为需要使用call,apply,bind来弥补缺漏。这个缺漏之处就是函数的this值,本质上来说是函数的执行上下文,call,apply和bind就是用来改变函数的执行上下文的。

函数也是对象

  在JS中,函数其实是对象,可以看做是构造函数Function()的实例。那么作为对象,就必然具有方法,所以函数可以使用apply,call和bind方法。这一点告诉我们,这3个方法是由函数本身调用的。

上下文(context)

  JS中函数是有上下文这个概念的,怎么理解呢?可以理解为函数所处的环境状态,这个环境状态提供了函数调用所需要的相关信息。比如,我们看以下的这段 JavaScript 代码:

var b = {}
let c = 1
this.a = 2;

要想正确执行它,我们需要知道以下信息:

  1. var 把变量b声明到哪里;
  2. b表示哪个变量;
  3. b的原型是哪个对象;
  4. let把c声明到哪里;
  5. this指向哪个对象;
    这些信息就需要执行上下文来提供了,也就是执行环境。除了执行上下文,还有定义上下文,指的是函数定义时的环境。这两者都是函数的环境,不同的是所处的时刻不一样。

this值

  this是JS语言的一个关键字。它是函数运行时,在函数体内部自动生成的一个对象,只能在函数内部使用。

function test() {
    this.x = 1;
}

上面代码中,函数test运行时,内部会自动有一个this对象可以使用。那么this的值是什么呢?不同的函数调用场合,this的值也是不一样。总的来说,this就是函数运行时所在的环境对象。

this的用法

  1. 纯粹函数的调用
    这是函数最普通的调用,这里的this代表的就是全局对象
var x = 1;
function test() {
   console.log(this.x);
}
test();  // 1
  1. 作为对象方法的调用
    当函数作为对象的方法调用时,this代表的就是这个上级对象。
function test() {
  console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;
obj.m(); // 1
  1. 作为构造函数调用
    构造函数是指可以通过构造函数本身生成一个新的对象的函数,它也是函数。我们一般使用new关键字来调用构造函数。这里的this指的就是这个新对象,或者叫做实例。
function Person() {
    this.name  = '龙傲天'
}

var person = new Person()
console.log(person.name) // 龙傲天 
  1. 箭头函数
    箭头函数是ES6引入的新语法,写起来简洁明了。而且重要的是箭头函数里的this值比较特殊,不受调用时的环境影响而改变。它始终都是继承自函数定义时上级对象的this值。
var o = {}
o.foo = function foo(){
    console.log(this);
    return () => {
        console.log(this);
        return () => console.log(this);
    }
}

o.foo()()(); // o, o, o

这个例子中,我们定义了三层嵌套的函数,最外层为普通函数,两层都是箭头函数。这里调用三个函数,获得的 this 值是一致的,都是对象 o。

改变函数内部this的方法

JS还提供了一些方法,在函数调用时改变函数内部的this值。那就是Function.prototype.call()、Function.prototype.apply()和Function.prototype.bind()。这里要注意,这三个方法是不能改变箭头函数的this值的,只能传入参数。

  • call()和apply()
function foo(a, b, c){
    console.log(this);
    console.log(a, b, c);
}
foo.call({}, 1, 2, 3);
foo.apply({}, [1, 2, 3]);

如上面代码所示,函数foo的this值被call和apply从全局对象改为了空对象{}。这两个方法的语法是一样的,只是传参方式有所区别。

  • bind()
    bind()方法生成了一个绑定了this值的新函数。
function foo(a, b, c){
    console.log(this);
    console.log(a, b, c);
}

foo.bind({}, [1, 2, 3])();

参考文章

1. 深入浅出 妙用Javascript中apply、call、bind
2. [译] JavaScript 中至关重要的 Apply, Call 和 Bind
3. Javascript 的 this 用法——阮一峰
4. 《重学前端》18讲

相关文章

网友评论

      本文标题:JS中的this值

      本文链接:https://www.haomeiwen.com/subject/herxuqtx.html