IT修真院·小课堂丨互联网职业小课堂在线学习平台

课堂课题:

简述JS中this的指向

关联任务:

任务二

直播时间:

2019-09-08 15:00:00


课堂内容:

视频链接:

PPT链接:

提交按钮:

小课堂内容格式


标题:

【修真院xx(职业)小课堂】课题名称

开场语:

大家好,我是IT修真院XX分院第X期的学员XX,一枚正直纯洁善良的XX程序员,今天给大家分享一下,修真院官网XX(职业)任务X,深度思考中的知识点——XXX

(1)背景介绍:

背景介绍的时候,尽可能的要宽广,讲清楚来龙去脉,讲清楚为什么会需要这个技术。

(2)知识剖析:

讲知识点的时候,尽可能的成体系,学会成体系的去给别人介绍知识。现在很多做的都是零散的,没有分类。

(3)常见问题:

最少列出1个常见问题。

(4)解决方案:

写清楚常见问题的解决方案。

(5)编码实战:

尽可能的去寻找在真实项目中在用的。如果你能找到某个网站在用你说的知识点,这是最好的。学以致用,否则当成练习题就没有意义了。多准备一些demo,讲解过程中将知识点和demo结合,便于大家理解所讲解的知识点。

(6)拓展思考:

知识点之外的拓展思考,由分享人进行讲解,这些东西就是所谓的深度,也是一个人技术水准高低比较的表现。

(7)参考文献:

引入参加文献的时候,在引用的句子后面加上序号【1】。参考文献中列出详细来源。不要去抄别人的东西,这是一个基本的态度。

(8)更多讨论:

Q1:提问人:问题?
A1:回答人(可以是分享人,也可以是其他学员):回答
Q2:提问人:问题?
A2:回答人(可以是分享人,也可以是其他学员):回答
Q3:提问人:问题?
A3:回答人(可以是分享人,也可以是其他学员):回答

(9)鸣谢:

感谢XX、XX师兄,此教程是在他们之前技术分享的基础上完善而成。

(10)结束语:

今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~

简述JS中this的指向     中品

辅导师兄 [真传弟子]JS-张林骞


修真院web小课堂】简述js中this的指向


大家好,我是IT修真院北京分院第40期的学员姚富成,今天给大家分享一下,深度思考中的知识点——简述js中this的指向


  1. 1、背景介绍

js 的 this 是个比较令人头疼的东西,尤其是在面试的时候,深受面试官的喜爱。我们今天来谈谈 js 中的 this


this是什么

理解this之前, 先纠正一个观点,this既不指向函数自身,也不指函数的词法作用域。如果仅通过this的英文解释,太容易产生误导了。它实际是在函数被调用时才发生的绑定,也就是说this具体指向什么,取决于你是怎么调用的函数。


为什么要用this

this机制提供了更优雅的方式来隐含地“传递”一个对象引用,导致更加干净的 API 设计和更容易的复用。当我们的代码和使用环境约复杂,我们就越能感受到 this的重要性


2、知识剖析

this 绑定规则

this的4种绑定规则分别是:默认绑定、隐式绑定、显示绑定、new 绑定。优先级从低到高


默认绑定

什么叫默认绑定,即没有其他绑定规则存在时的默认规则。这也是函数调用中最常用的规则。

    function foo(){

        var a = 1 ;

    console.log(this.a);    // 10

    }

    var a = 10;

    foo();


这种就是典型的默认绑定,我们看看foo调用的位置,”光杆司令“,像 这种直接使用而不带任何修饰的函数调用 ,就 默认且只能 应用 默认绑定。

注意:默认绑定一般是绑定window上,严格模式下 是undefined。


  

隐式绑定

除了直接对函数进行调用外,有些情况是,函数的调用是在某个对象上触发的,即调用位置上存在上下文对象。


    function foo(){

        console.log(this.a);

    }

    var obj = {

        a : 10,

        foo : foo

    }

    foo();     // undefined

                        

    obj.foo();  // 10


foo()的这个写法就是我们刚刚写的默认绑定,等价于打印window.a,故输出undefined ,。

下面obj.foo()这种大家应该经常写,这其实就是我们要讨论的隐性绑定 。

函数foo执行的时候有了上下文对象,即 obj。这种情况下,函数里的this默认绑定为上下文对象,等价于打印obj.a,故输出10 。

如果是链性的关系,比如 xx.yy.obj.foo();, 上下文取函数的直接上级,即紧挨着的那个,或者说对象链的最后一个。

         


隐式丢失(函数别名)

这里存在一个陷阱,大家在分析调用过程时,要特别小心


    function foo() { 

        onsole.log( this.a );

    }

                        

    var a = 2;

                        

    var obj = { 

        a: 3,

        foo: foo 

    };

                        

    var bar = obj.foo;

        bar(); //2


为什么bar() 打印的结果是2,obj.foo 赋值给bar,那调用bar()为什么没有触发隐式绑定,使用的是默认绑定呢

这里有个概念要理解清楚,obj.foo 是引用属性,赋值给bar的实际上就是foo函数(即:bar指向foo本身)。

那么,实际的调用关系是:通过bar找到foo函数,进行调用。整个调用过程并没有obj的参数,所以是默认绑定,全局属性a。


隐式丢失(回调函数)

           

    function foo() { 

        console.log( this.a );

    }

                        

    var a = 2;

                        

    var obj = { 

        a: 3,

        foo: foo 

    };

                        

    setTimeout( obj.foo, 100 ); // 2


同样的道理,虽然参传是obj.foo,因为是引用关系,所以传参实际上传的就是foo对象本身的引用。对于setTimeout的调用,还是 setTimeout -> 获取参数中foo的引用参数 -> 执行foo 函数,中间没有obj的参与。这里依旧进行的是默认绑定。


显性绑定

隐性绑定的限制

在我们刚刚的 隐性绑定中有一个致命的限制,就是上下文必须包含我们的函数 ,例:var obj = { foo : foo},如果上下文不包含我们的函数用隐性绑定明显是要出错的,不可能每个对象都要加这个函数 ,那样的话扩展,维护性太差了,我们接下来聊的就是直接 给函数强制性绑定this。


call apply bind

这里我们就要用到 js 给我们提供的函数 call 和 apply,它们的作用都是改变函数的this指向,第一个参数都是 设置this对象。


    function foo(a,b){

        console.log(a+b);

    }

    foo.call(null,'海洋','饼干');     // 海洋饼干  这里this指向不重要就写null了

    foo.apply(null, ['海洋','饼干'] );     // 海洋饼干



两个函数的区别:

call从第二个参数开始所有的参数都是 原函数的参数。

apply只接受两个参数,且第二个参数必须是数组,这个数组代表原函数的参数列表。

bind只有一个函数,且不会立刻执行,只是将一个值绑定到函数的this上,并将绑定好的函数返回。例:

          

    function foo(){

        console.log(this.a);

    }

    var obj = { a : 10 };

                            

    foo = foo.bind(obj);

    foo();   //10



    function foo(){

        console.log(this.a);

    }

    ar obj = {

        a : 10            //去掉里面的foo

    }

    foo.call(obj);        // 10 

    

将隐性绑定例子中的 上下文对象 里的函数去掉了,显然现在不能用 上下文.函数

这种形式来调用函数,大家看代码里的显性绑定代码foo.call(obj),看起来很怪,和我们之前所了解的函数调用不一样。

其实call 是 foo上的一个函数,在改变this指向的同时执行这个函数。

 

new 绑定

创建一个新对象少不了一个概念,那就是构造函数,传统的面向对象 构造函数 是类里的一种特殊函数,要创建对象时使用new 类名()的形式去调用类中的构造函数,而js中就不一样了。js中的只要用new修饰的 函数就是'构造函数',准确来说是 函数的构造调用,因为在js中并不存在所谓的'构造函数'。


>那么用new 做到函数的构造调用后,js帮我们做了什么工作呢:

创建一个新对象把这个新对象的__proto__属性指向 原函数的prototype属性。(即继承原函数的原型)将这个新对象绑定到 此函数的this上 。返回新对象,如果这个函数没有返回其他对象。

第三条就是我们下面要聊的new绑定


    function foo(){

        this.a = 10;

        console.log(this);

    }

    foo();       // window对象

    console.log(window.a);    // 10   默认绑定

                        

    var obj = new foo();      // foo{ a : 10 }  创建的新对象的默认名为函数名

    // 然后等价于 foo { a : 10 };  var obj = foo;

    console.log(obj.a);       // 10    new绑定

       

使用new调用函数后,函数会 以自己的名字 命名 和 创建 一个新的对象,并返回。

特别注意 : 如果原函数返回一个对象类型,那么将无法返回新对象,你将丢失绑定this的新对象


    unction foo(){

        this.a = 10;

        return new String("捣蛋鬼");

    }

    var obj = new foo();

    console.log(obj.a);       // undefined

    console.log(obj);         // "捣蛋鬼"


3.常见问题

4.解决方案

5.编码实战

6.扩展思考

this绑定优先级

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


7.参考文献

https://segmentfault.com/a/1190000011194676


8.更多讨论


评论

[北京|结业弟子]JS-肖明明 发表于 2019-10-07 09:18:01 #1

默认绑定,显示绑定,隐式绑定这种概念是不是多余的

回复

请您登录 后进行评论