js中this详解

学了这么久前端后变成搜集各个大佬的博客

转自https://zhuanlan.zhihu.com/p/82504422

解释下JavaScript中的this是怎么工作的?
来来来,给你看下面这一段程序,这里的this.bar打印出来是什么值?下面这个this.bar打印出来又是什么值呢?

在前端的面试当中,this的指向是面试官一定要问的问题。废话少说,这篇文章带你10分钟搞懂this的世界。

本文参考了Kyle Simpson的《高级JavaScript》(Advanced JavaScript)这门课程,例子也选取了其中的例子。如果你也想成为前端大师,那么他的课程会是你前进路上的助推器!

1. 四种this绑定

这四种绑定分类是基于调用点(call site),即函数是在哪里被谁调用的。也就是说this指向谁,跟函数在哪里定义没有关系,而是取决于被谁调用。下面我们具体分析每种绑定情况。

  • 默认绑定与隐式绑定

让我们看看下面这个例子:

function foo() {
console.log(this.bar);
}
var bar = “bar1”;
var o2 = {bar: “bar2”, foo: foo};
var o3 = {bar: “bar3”, foo: foo};
foo(); // “bar1” – 默认绑定
o2.foo(); // “bar2” – 隐式绑定
o3.foo(); // “bar3” – 隐式绑定
foo()这种调用方法,就是默认绑定。如果在非严格模式下,this就是全局对象,浏览器当中就是window。而如果在严格模式(use strict)下,this就会是undefined。

之所以这是默认绑定,因为foo的调用不属于任何人,前面没有任何限定条件。这是最简单的绑定。

o2.foo()和o3.foo()这两种调用方法,都是隐式绑定。Foo是作为o2和o3的方法而调用的,那么谁调用foo,this就指向谁。在上面的例子中,o2.foo()中的this指向o2,因此this.bar就是o2当中的bar: “bar2”;同理,o3.foo()打印出来的就是o3中的”bar3”。

  • 显式绑定

我们看一个显式绑定的例子:

function foo() {
console.log(this.bar);
}
var bar = “bar1”;
var obj = {bar: “bar2”};

foo(); // “bar1” 默认绑定
foo.call(obj); // “bar2” 显式绑定,使用obj作为"this"
如果foo是通过call、apply或者bind调用的,那么这种调用就是显式绑定。这种绑定中,this的指向就是这三个函数中传递的第一个参数。

  • 关键字new绑定

请看下面这个例子:

function foo() {
this.baz = “baz”;
console.log(this.bar + " " + baz);
}
var bar = “bar”;
var baz = new foo();
如果把new这个关键字放在一个函数调用的前面,JS编译器会做这四件事情:

创建一个新的空的对象
把这个对象链接到原型对象上
这个对象被绑定为this
如果这个函数不返回任何东西,那么就会默认return this
关于new这个关键字的四步,看不懂也没事,有空的话会另写一篇文章具体介绍一下。不过,我们从这四步可以看出,如果在函数调用前面加上new,那么这个函数中的this就是这个新的对象。

上面的例子,最终会输出undefined undefined。这是因为baz这个变量并没有bar这个属性,而baz此时只被定义,没有被赋值,因此baz也是undefined。

  • 箭头函数

箭头函数会无视以上所有的规则,this的值就是函数创建时候所在的lexical scope中的this,而和调用方式无关。可以对比下面两个例子:

function Person(){
this.age = 0;
setTimeout(function () {
console.log(this.age); // 输出undefined
}, 1000);
}
var p = new Person();

function Person(){
this.age = 10;
setTimeout(()=> {
console.log(this.age); // 输出10
}, 1000);
}
var p = new Person();
在上面没有使用箭头函数的例子当中,setTimeout内部的函数是被global调用的,而global没有age这个属性,因此输出undefined。

第二个例子使用了箭头函数,this就会使用lexical scope中的this,就是Person,因此输出10。

绑定优先级
如果多重绑定规格都适用,那么绑定规则的优先级顺序是这样的:

  1. 箭头函数
  2. 关键字new调
  3. 显式绑定
  4. 隐式绑定
  5. 默认绑定

箭头函数优先级最高,会无视2-5绑定规则。而默认绑定优先级最低,只有其他绑定都不使用的时候,才会使用默认绑定。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值