关于this的深入认识

2017-09-16  本文已影响0人  悲欢自饮丶

从学习前端开始已经大概要两个月了,这几天突然发现this并没有想想中这么简单,之前很长一段时间对于this的认识停留在它的指向方法上。

那时对this只是一个简单的认识,这么说来也没有任何理解上的问题。但是学到后来,发现this的应用光靠这些基础已经远远不够了。

从绑定方式上我姑且把它分为4种方式。

默认绑定

多说无用,下面来看代码.

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

      (function(){
        "use strict";
        foo();
      })()

这个时候严格模式不会影响默认绑定规则,此时输出的是2

        function foo() {
          "use strict";
          console.log( this.a );
        }
        var a = 2;
        foo(); 

现在这个时候会报错,a为undefined.

隐式绑定

      function foo() {
        console.log( this.a );
        }
        var obj = {
            a: 2,
            foo: foo
        };
        obj.foo(); 

毋庸置疑this指向调用者obj,输出2

    function foo() {
            console.log( this.a );
        }
        var obj2 = {
            a: 42,
            foo: foo
        };
        var obj1 = {
            a: 2,
            obj2: obj2
        };
        obj1.obj2.foo(); 

这个时候this指向obj2,输出42

    function foo() {
            console.log( this.a );
        }
        var a = "hello word"; 
        var obj = {
            a: 2,
            foo: foo
        };
        
        var bar = obj.foo; 
        bar(); 

这个时候会发生隐式丢失,this指向全局对象:hello word

        function foo() {
            console.log( this.a );
        }

        function doFoo(fn) {
            fn(); 
        }

        var a = "hello word"; 
        var obj = {
            a: 2,
            foo: foo
        };
        
        doFoo( obj.foo ); 

这个时候会发生隐式丢失,this指向全局对象:hello word

如果你把函数传入语言内置的函数而不是传入你自己声明的函数,你会发现结果是一样的,没有区别,比如定时器的内置函数:

        function foo() {
            console.log( this.a );
        }
        
        var a = "hello word"; 
        var obj = {
            a: 2,
            foo: foo
        };
        
        setTimeout( obj.foo, 1000 );  

结果输出的仍然是:hello word

显示绑定

        var a =0;
        function foo() {
            console.log( this.a );
        }
        var obj = {
            a:1
        };
        var obj2 = {
            a:2
        };
        var obj3 = {
            a:3
        };
        foo();
        foo.call( obj );
        foo.apply( obj2 );
        foo.call( obj3 );

如果没有给foo使用call方法,foo使用的就是默认绑定,foo()输出0,。使用call apply方法,输出分别为1,2,3

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

        var obj = {
            a:2
        };

        var obj_test = {
            a:"test"
        };

        var bar = function() {
            foo.call( obj );
        };
        
        bar(); //2
        setTimeout( bar, 1000 ); // 2
        bar.call( obj_test ); //2   

硬绑定的bar不可能再修改它的this(指的是foo中的this),是不是解决了之前的隐式丢失。(定时器内部this的调用是独立调用)

-简单的辅助绑定函数bind函数的作用:返回一个新的函数,并且指定该新函数的this指向

        function bind(fn, obj) {
            return function() {
                    return fn.apply( obj, arguments );
                };
        }
        
        var obj = {
            a:2
        };
        var obj_test = {
            a:22
        };
        
        
        var bar = bind( foo, obj);
        var b = bar(3); // 2 3 undefined
        console.log( b ); // 5
        bar.call(obj_test,3);//2 3 undefined

有了bind函数,我们可以把经过绑定的函数拿去使用(这样它就有默认值了)

new绑定

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

使用 new 来调用 foo(..) 时,我们会构造一个新对象并把它绑定到 foo(..) 调用中的 this 上。new 是最后一种可以影响函数调用时 this 绑定行为的方法,我们称之为 new 绑定。

绑定的优先级

最后我们来说一说绑定的优先级

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

绑定例外

es6中胖箭头this指向与我们现在的规则不一样

被忽略的this:apply call bind(null) this----> window

柯里化:为函数去预绑定参数

var obj = Object.create(null)

之后如果有机会我会在下面继续补充的。。。。

上一篇 下一篇

猜你喜欢

热点阅读