最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • JavaScript This ( Context ) 之 完全拿下

    正文概述 掘金(SandySY)   2021-01-18   347

    JavaScript This ( Context ) 之 完全拿下

    鉴于this风骚的运作方式,各大厂面试和基础书籍阅读中,对this的理解是永不过时的话题,这块骨头既然这么难啃干净,那就干脆将其大卸八块,高压锅一压,营养一锅端;话不多说,这就完全拿下的。

    1 描述概念

    this说白了就是找老大,找拥有当前上下文(context)的对象(context object)。大致可以分为八层(也可以是六层,还有说是四层,都对都没问题),层数越高权力越大,this只会认最大的。

    2 点兵点将

    咱们直接整最详细的,准备一个函数foo,首行代码控制严格模式开关,就像这样:

    'use strict';
    var that;
    function foo(params) {
      that = this;
      console.log('this是:', this);
    }
    

    2.1 直接调用

    // 1-直接调用 window || undefined (严格模式)
    foo();
    

    这是一个兜底的存在,在普通情况下this就是全局,浏览器里就是window;在use strict的情况下就是undefined。

    2.2 对象调用

    如果用到this的那个函数是属于某个 context object 的,那么这个 context object 绑定到this。比如下面的例子:

    //2-挂载在对象上,然后执行 -> 对象
    let arr = [1, 2, 3];
    arr.fn = foo;
    arr.fn();
    

    2.3 定时器调用

    这个玩儿法还有很多类似的,比如用户点击IO,宏任务响应等。

    //3-定时器--window
    setTimeout(foo, 100);
    

    对,这里始终是window,因为是任务队列里面的,当被线程推到执行调用栈,此时的调用环境就是window

    2.4 工具函数(forEach)

    [(1, 2, 3)].forEach(function (item) {
      console.warn(this, item);
    }); //window || undefined 3
    [1, 2, 3].forEach(function (item) {
      console.warn(this, item);
    }); //window || undefined 1-3
    

    可以看到forEach这样的遍历函数,其this和第一种直接一样,根据是否是严格模式反馈兜底的结果,至于为什么不是前面的对象调用,仔细想想,不难发现原因是吧。

    2.5 工具函数(call|apply)

    Object.prototype.call和Object.prototype.apply,它们可以通过参数指定this,具体用法和差异在此就不赘述,有需要可以上MDN。

    foo.call(12);			// 12
    foo.call(Date()); 		// ... (中国标准时间)
    foo.call('ajflk'); 		// ajflk
    foo.apply(/dfjlk/); 		// /dfjlk/
    //注意this是不可以直接赋值的哦,this = 2会报ReferenceError。
    

    2.6 工具函数(bind)

    Object.prototype.bind,它不但通过一个新函数来提供永久的绑定,还会覆盖以上工具函数的命令。

    let _obj = { name: 'demo' };
    let foo2 = foo.bind(_obj);
    foo2();  		// {name: "demo"}
    foo2.call(_obj2);	// {name: "demo"}
    

    2.7 new 当成构造函数使用

    这是一个比较容易忽略的绑定this的地方。当我们new一个函数时,就会自动把this绑定在新对象上,然后再调用这个函数。它会覆盖bind的绑定。

    let _obj = { name: 'demo' };
    new foo();		// foo {}
    let foo2 = foo.bind(_obj);
    foo2();			// {name: "demo"}
    new foo2();		// foo {}
    

    2.8 箭头函数

    ES2015 的箭头函数很酷,几乎所有前端开发人员都爱不释手。其原因就是在箭头函数里,this不再妖艳,被永远封印到当前词法作用域之中,称作 Lexical this ,在代码运行前就可以确定。没有其他途径可以覆盖。
    这样的好处就是方便让回调函数的this使用当前的作用域,不怕引起混淆。所以对于箭头函数,只要看它在哪里创建的就行。如果对词法作用域感兴趣可以看看这里。

    let fun = () => console.log('fun this is', this);
    fun(); 			// fun this is window
    // new fun(); 		// TypeError
    var obj1 = {
      name: 'obj1',
      funThis() {
        var func = () => console.log('funThis this is', this);
        return func();
      },
    };
    fun.call(obj1); 	// fun this is window
    var funBind = fun.bind(obj1);
    funBind(); 		// fun this is window
    obj1.funThis(); 	// funThis this is obj1
    var obj2 = {
      name: 'obj2',
      funThis: obj1.funThis,
    };
    obj2.funThis(); 	// funThis this is obj2
    

    箭头函数的核心就是一句话:“对于箭头函数,只要看它在哪里创建”。

    3 总结

    啃骨头就得啃干净,this这么看来就简单了,但是简单的东西有那么多文章来描述它定义它,那其实也就不见得是多简单,所以,咱们还是平常心。

    为了方便阅读理解,本文代码已经上传Github
    文中如有错误,欢迎在评论区指正,如果有所帮助,欢迎点赞和关注


    起源地下载网 » JavaScript This ( Context ) 之 完全拿下

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元