zoukankan      html  css  js  c++  java
  • 深入理解this

                你可能听过很多this,就像C#中的this就是指向一个他的实例对象,

          但是在javascript中,我可能要告诉你,他是在运行时动态绑定的

    他指向什么,完全取决于函数在哪里调用                                                                  

            在这里还要说明一个东西,调用栈----------->通俗的来讲,就是为了到达一个方法所调用的所有方法

        我们可以用浏览器自带的调试工具来查看

            function foo(){
                console.log(this.a);
            }
            var b={
                a:10,
                foo:foo
            };
            b.foo();//10

        从运行的结果,我们就可以看出来,当调用b.foo()时this被绑定到了b   

    了解了调用栈以后,我们在来了解一个词,调用位置                                                                    

       调用位置,顾名思意,也就是我调用这个函数的上一个位置,也叫做调用位置0-0

            function foo(){
                console.log(this.a);
            }
            var a=20;
            foo();//20

     仔细的人就会发现,上面的调用位置和下面的调用位置都是全局,那么是什么让他们产生了差异?

    如果你仔细的看的话,就会发现他们的差别就在于调用foo()的方法不同,上面的是b.foo(),而下面的只是foo();

      也就是这一点的差异,让绑定发生的变化

    为了说明这点我们需要指明绑定时的4个规则

    1.默认绑定                                                                                                                        

            function foo(){
                console.log(this.a);
            }
            var a=20;
            foo();//20

    独立函数调用。可以把这条规则看作是无法应用其他规则时的默认规则。

      在这里需要说明的是,只有在非严模式下,默认绑定才会绑定到全局,否则会报ReferencesError错误

    2.隐式绑定                                                                                                                          

    另一条需要考虑的规则是调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含,不过这种说法可能会造成一些误导。

     我们就拿上面的那个例子来说

            function foo(){
                console.log(this.a);
            }
            var b={
                a:10,
                foo:foo
            };
            a=20;
            b.foo();//10
            foo();//20

    在这个例子中,我们通过b.foo();来调用foo()函数,在这里需要注意的是b.foo只是对foo()函数的一个引用

    那么你可能就会说既然只是一个引用,那么我调用它和直接调用它没有什么区别吧,但是,我们还记得第一个标题?

      this是在被调用时被绑定的!!!  而我们调用的地方正是b,所有this就指向了b!!!!!!!!!!!!

    当然使用这种隐式绑定也有一定的缺点 !!!           请看下面的例子                                                   

            function foo(){
                console.log(this.a);
            }
            var b={
                a:10,
                foo:foo
            };
            a=20;
            var bar=b.foo;
            bar();//20 这里是20你想通了吗?
            

    一种更微妙、更常见并且更出乎意料的情况发生在传入回调函数时                                                

            function foo(){
                console.log(this.a);
            }
            var b={
                a:10,
                foo:foo
            };
            a=20;
            function bind(fn){
                fn();
            }
            bind(b.foo);//20 在这里输出的是20 是因为b.foo 仅仅就是一个函数的引用,所以他调用了默认绑定,指向this

    上面的例子和下面的结果一样

            function foo(){
                console.log(this.a);
            }
            var b={
                a:10,
                foo:foo
            };
            a=20;
            setTimeout(b.foo,1000);//20  可以看到结果和上面一样!!!!!!!!

    3.显示绑定                                                                                                                         

      Call(this,参数)                                                                                                           

            var b1={
                a:10,
                foo:function foo(){
                    console.log(this.a);
                }
            };
            var b2={a:20};
            
            b1.foo.call(b2);//20 在这里我们显示的让this指向了b2这个对象

      Apply(this,参数数组)                                                                                                   

            var b1={
                a:10,
                foo:function foo(t,e){
                    console.log(this.a+t+e);
                }
            };
            var b2={a:20};
            
            b1.foo.apply(b2,[1,2]);//23  我们可以看到,他们除了在参数的传递上不同外,其他的都一样

    bind                                                                                                           

            function foo(){
                console.log(this.a);
            }
            var a=200;
            var b={a:100};
            setTimeout(foo.bind(b)//100
            ,1000);

    当然在这里有必要说一下bind的语法 function.bind(Object),也就是将一个对象绑定到一个函数上

    4.New绑定                                                                                                                      

    使用 new 来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。
      1. 创建(或者说构造)一个全新的对象。
      2. 这个新对象会被执行 [[ 原型 ]] 连接。
      3. 这个新对象会绑定到函数调用的 this 。
      4. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象

    function foo(a) {
    this.a = a;
    }
    var bar = new foo(2);
    console.log( bar.a ); // 2

    那么有这4个绑定规则,哪个的优先权更高呢?---------------------->请看下章

    Hold on, everything is possible.
  • 相关阅读:
    Codeforces Round #384 (Div. 2) 解题报告
    Codeforces Round #383 (Div. 2) 解题报告
    (DFS、bitset)AOJ-0525 Osenbei
    (DFS、全排列)POJ-3187 Backward Digit Sums
    自考新教材-p169
    自考新教材-p167
    自考新教材-p166
    自考新教材-p165
    自考新教材-p161
    自考新教材-p159
  • 原文地址:https://www.cnblogs.com/student-note/p/6641517.html
Copyright © 2011-2022 走看看