• js中this的绑定


        人们对于this的绑定常常有两个误解,一:指向函数本身,二:指向函数作用域。这两种想法都是错的,this并不指向函数本身,也不指向函数作用域。

    function  foo(){
          this.count++;
    }
    foo.count = 0;
    for(var i = 0 ; i<5 ; i++){
          foo();
    }
    alert( foo.count );   //  0

       因为this不指向函数本身,所以foo.count的值依然是0。

    function foo(){
        var a = 1 ;
        alert(this.a);
    }
    var a = 2;
    foo();   //  2

        因为this不指向函数作用域,所以输出的是2。

        this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。

        this的绑定一共有四种绑定:1:默认绑定(即没有明确的调用对象)

                                            2:隐性绑定(即作为对象方法调用,this会被绑定到该对象)

                                            3:显性绑定(使用apply()和call()调用,两个方法的第一个参数为一个对象,this被绑定到该对象)  

                                            4:new绑定(使用new来调用函数,会构造一个新对象,并且把this绑定到该对象)

          一:默认绑定   (即没有明确的调用对象)     

    function foo(){
        var a = 1 ;
        alert(this.a);
    }
    var a = 2;
    foo();   //  2    (非严格模式下)

         没有明确调用对象,this会被绑定到window对象,所以this.a就是window.a,即为2。不过这得在非严格模式下,只有在非严格模式下this才会被绑定到window对象,而在严格模式下,this被绑定到undefined。

           二:隐性绑定   (即作为对象方法调用,this会被绑定到该对象)

    function  foo(){
          var  a = 1;
          alert(this.a);
    }
    var  obj = {
          a:2,
          foo:foo
    };
    obj.foo();    // 2

        obj对象调用foo()函数,this被绑定到obj对象,所以输出了obj对象的a的值2。

         对象属性引用链中只有最后一层会影响调用位置

    function  foo(){
            alert(this.a);
    }
    var  obj2 = {
          a:2,
          foo:foo
    };
    var obj1 = {
          a:1,
          obj2:obj2 
    }; 
    obj1.obj2.foo(); //2

        obj1和obj2两个对象连续调用,this会被绑定到最后一个对象,即obj2,所以输出2

        隐式丢失:被隐式绑定的函数会丢失绑定对象,有两种情况会丢失,一种为引用,另一种为回调函数。

             引用:

    function  foo(){
        alert(this.a);
    }
    var  obj = {
          a:1,
          foo:foo
    };
    var bar = obj.foo;
    var a = "global  1";
    bar();   //global  1

            bar是obj.foo的一个引用,实际上它引用的是foo函数本身,所以this被绑定到window对象,输出的是"global 1"

           回调函数:

    function    foo(){
         alert(this.a);
    }
    function  doFoo(fn){    
          fn();                               
    }
    var  obj = {
        a = 1,
        foo:foo
    }
    var a  =  "global   1";
    doFoo(obj.foo);    //"global  1"

        调用回调函数的函数可能会修改this

         三:显性绑定(使用apply()和call()调用,两个方法的第一个参数为一个对象,this被绑定到该对象) 

    function  foo(){
          alert(this.a);
    }
    var  obj = {
           a:1
    };
    foo.call(obj);  //  1

        call()的参数若为空,默认调用window对象,若为一个原始值(字符串类型,布尔类型或者数字类型),则这个原始值会被转换成它的对象形式(new  String(),new Boolean() 或者 new Number()),这被称为“装箱”

         硬绑定———显示绑定的一种变形

                优点:可以解决丢失绑定问题

                缺点:硬绑定后不可能再修改它的this   

    function  foo(){
         alert(this.a);
    }
    var obj = {
         a:2
    };
    var  bar = function(){
          foo.call(obj);
    };
    bar();   // 2
    setTimeout(bar,100);  // 2
    bar.call(window);  // 2

       ES5中提供了内置方法Function.prototype.bind

    function foo(something){
          alert(this.a, something);
          return  this.a + something;
    }
    var obj = {
        a:2
    };
    var  bar = foo.bind(obj);
    var  b = bar(3);   //  2  3
    alert(b);   // 5

    bind()会返回一个硬编码的新函数,它会把参数设置为this的上下文并调用原始函数

    四:new绑定(使用new来调用函数,会构造一个新对象,并且把this绑定到该对象)

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

    this绑定的四条规则的优先级: new绑定  >  显示绑定  >  隐式绑定   >  默认绑定

     

  • 相关阅读:
    JS 循环遍历json
    客户端获取ip
    jquery 常用获取值得方法汇总
    C# MATLAB混合编程
    java设计模式之抽象工厂模式学习
    java设计模式之工厂模式学习
    java设计模式之装饰者模式学习
    本周任务
    模仿jquery的data
    js中random的应用
  • 原文地址:https://www.cnblogs.com/yezi-dream/p/5719630.html
Copyright © 2020-2023  润新知