资讯专栏INFORMATION COLUMN

你不知道的js中关于this绑定机制的解析[看完还不懂算我输]

dunizb / 877人阅读

摘要:绑定书中提到在中,实际上并不存在所谓的构造函数,只有对于函数的构造调用。规则使用构造调用的时候,会自动绑定在期间创建的对象上。指向新创建的对象绑定比隐式绑定优先级高。

前言

最近正在看《你不知道的JavaScript》,里面关于this绑定机制的部分讲的特别好,很清晰,这部分对我们js的使用也是相当关键的,并且这也是一个面试的高频考点,所以整理一篇文章分享一下这部分的内容,相信看本文的解析,你一定会有所收获的,如果喜欢的话可以点波赞/关注,支持一下。

个人博客了解一下:obkoro1.com
为什么要用this:
function identify() {
  console.log("Hello,I"m " + this.name);
}
let me = {
  name: "Kyle"
};
let you = {
  name: "Reader"
};
identify.call(me); // Hello,I"m Kyle
identify.call(you); // Hello,I"m Reader

这个简单的栗子,可以在不同的对象中复用函数identify,不用针对每个对象编写一个新函数。

this解决的问题:

this提供了一种更优雅的方法来隐式"传递"一个对象的引用,因此可以将API设计得更加简洁并且易于复用

this的四种绑定规则: 默认绑定:

规则:在非严格模式下,默认绑定的this指向全局对象,严格模式下this指向undefined

function foo() {
  console.log(this.a); // this指向全局对象
}
var a = 2;
foo(); // 2
function foo2() {
  "use strict"; // 严格模式this绑定到undefined
  console.log(this.a); 
}
foo2(); // TypeError:a undefined

默认绑定规则如上述栗子,书中还提到了一个微妙的细节:

function foo() {
  console.log(this.a); // foo函数不是严格模式 默认绑定全局对象
}
var a = 2;
function foo2(){
  "use strict";
  foo(); // 严格模式下调用其他函数,不影响默认绑定
}
foo2(); // 2

所以:对于默认绑定来说,决定this绑定对象的是函数体是否处于严格模式,严格指向undefined,非严格指向全局对象。

通常不会在代码中混用严格模式和非严格模式,所以这种情况很罕见,知道一下就可以了,避免某些{{BANNED}}的面试题挖坑。

隐式绑定:

规则:函数在调用位置,是否有上下文对象,如果有,那么this就会隐式绑定到这个对象上。

    function foo() {
      console.log(this.a);
    }
    var a = "Oops, global";
    let obj2 = {
      a: 2,
      foo: foo
    };
    let obj1 = {
      a: 22,
      obj2: obj2
    };
    obj2.foo(); // 2 this指向调用函数的对象
    obj1.obj2.foo(); // 2 this指向最后一层调用函数的对象
    
    // 隐式绑定丢失
    let bar = obj2.foo; // bar只是一个函数别名 是obj2.foo的一个引用
    bar(); // "Oops, global" - 指向全局

隐式绑定丢失:

隐式绑定丢失的问题:实际上就是函数调用时,并没有上下文对象,只是对函数的引用,所以会导致隐式绑定丢失。

同样的问题,还发生在传入回调函数中,这种情况更加常见,并且隐蔽,类似:

    test(obj2.foo); // 传入函数的引用,调用时也是没有上下文对象。
显式绑定:

就像我们上面看到的,如果单纯使用隐式绑定肯定没有办法得到期望的绑定,幸好我们还可以在某个对象上强制调用对象,从而将this绑定在这个函数上

规则:我们可以通过applycallbind将函数中的this绑定到指定对象上。

function foo() {
    console.log(this.a);
}
let obj = {
    a: 2
};
foo.call(obj); // 2

传入的不是对象:

如果你传入了一个原始值(字符串,布尔类型,数字类型),来当做this的绑定对象,这个原始值转换成它的对象形式。

如果你把null或者undefined作为this的绑定对象传入call/apply/bind,这些值会在调用时被忽略,实际应用的是默认绑定规则。

new绑定:
书中提到:在js中,实际上并不存在所谓的"构造函数",只有对于函数的"构造调用"。

new的时候会做哪些事情:

创建一个全新的对象

这个新对象会被执行 [[Prototype]] 连接。

这个新对象会绑定到函数调用的this

如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。

规则:使用构造调用的时候,this会自动绑定在new期间创建的对象上。

function foo(a) {
  this.a = a; // this绑定到bar上
}
let bar = new foo(2);
console.log(bar.a); // 2
this四种绑定规则的优先级

如果在某个调用位置应用了多条规则,如何确定哪条规则生效?

    obj.foo.call(obj2); // this指向obj2 显式绑定比隐式绑定优先级高。
    new obj.foo(); // thsi指向new新创建的对象 new绑定比隐式绑定优先级高。

显式绑定和new绑定无法直接比较((会报错),默认绑定是不应用其他规则之后的兜底绑定所以优先级最低,最后的结果是:

显式绑定 > 隐式绑定 > 默认绑定

new绑定 > 隐式绑定 > 默认绑定

箭头函数的this指向不会使用上述的四条规则:
function foo() {
  return () => {
    console.log(this.a);
  };
}
let obj1 = {
  a: 2
};
let obj2 = {
  a: 22
};
let bar = foo.call(obj1); // foo this指向obj1
bar.call(obj2); // 输出2 这里执行箭头函数 并试图绑定this指向到obj2

从上述栗子可以得出,箭头函数的this规则:

箭头函数中的this继承于它外面第一个不是箭头函数的函数的this指向

箭头函数的 this 一旦绑定了上下文,就不会被任何代码改变

结语

认真看完的话,相信你已经get到this的用法了,最后推荐一下《你不知道的JavaScript》,这本书真的很好,写的也很有趣,没看过的小伙伴抓紧入手了。

PS:目前离职中,大佬们有坑位可以介绍一下呀,base:上海长宁。

希望看完的朋友可以点个喜欢/关注,您的支持是对我最大的鼓励。

个人blog and 掘金个人主页,如需转载,请放上原文链接并署名。码字不易,感谢支持!

如果喜欢本文的话,欢迎关注我的订阅号,漫漫技术路,期待未来共同学习成长。

以上2018.6.30

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95874.html

相关文章

  • 十分钟快速了解《你不知道 JavaScript》(上卷)

    摘要:最近刚刚看完了你不知道的上卷,对有了更进一步的了解。你不知道的上卷由两部分组成,第一部分是作用域和闭包,第二部分是和对象原型。附录词法这一章并没有说明机制,只是介绍了中的箭头函数引入的行为词法。第章混合对象类类理论类的机制类的继承混入。 最近刚刚看完了《你不知道的 JavaScript》上卷,对 JavaScript 有了更进一步的了解。 《你不知道的 JavaScript》上卷由两部...

    赵春朋 评论0 收藏0
  • 记大四以来前端面试

    摘要:大四到校就开始了紧张的秋招。在此纪录一下大四以来的前端面试。面试准备准备简历。主要是牛客网,牛客网秋招和春招都有面经分享活动,很多拿到大厂的大牛会在上面分享面试经验。这段是调用函数的语句,调用了约好的函数,并且将数据当做参数传入。 前言 大三下学期因为眼睛患了过敏性结膜炎,只好在家养病,错过了宝贵的实习时间。大四到校就开始了紧张的秋招。拿到的第一个offer是一家厦门的公司,当时跟技术...

    刘福 评论0 收藏0
  • 记大四以来前端面试

    摘要:大四到校就开始了紧张的秋招。在此纪录一下大四以来的前端面试。面试准备准备简历。主要是牛客网,牛客网秋招和春招都有面经分享活动,很多拿到大厂的大牛会在上面分享面试经验。这段是调用函数的语句,调用了约好的函数,并且将数据当做参数传入。 前言 大三下学期因为眼睛患了过敏性结膜炎,只好在家养病,错过了宝贵的实习时间。大四到校就开始了紧张的秋招。拿到的第一个offer是一家厦门的公司,当时跟技术...

    galois 评论0 收藏0
  • JavaScript深入浅出

    摘要:理解的函数基础要搞好深入浅出原型使用原型模型,虽然这经常被当作缺点提及,但是只要善于运用,其实基于原型的继承模型比传统的类继承还要强大。中文指南基本操作指南二继续熟悉的几对方法,包括,,。商业转载请联系作者获得授权,非商业转载请注明出处。 怎样使用 this 因为本人属于伪前端,因此文中只看懂了 8 成左右,希望能够给大家带来帮助....(据说是阿里的前端妹子写的) this 的值到底...

    blair 评论0 收藏0
  • 你不知道javascript》中关this记录

    摘要:使用调用函数时,会自动执行以下操作创建一个全新的对象该对象会被执行连接该对象会绑定到函数调用的若函数没有返回其他对象,表达式中的函数调用会自动返回该对象。 使用this可以减少传入上下文对象,可以隐式传递一个对象引用。使API简洁而复用,可以自动引用合适的上下文对象。 【要注意的几个点】 1. this不一定指向自身; 2. this不一定指向函数作用域(因为作用域无法通过js代码访...

    tommego 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<