zoukankan      html  css  js  c++  java
  • 关于JavaScript中的this

    1.关于this的误会。

      误会(1):this指向所在函数本身。

        我们常常会对this产生各种误会,比如说我们可能认为this会指向所在函数本身,但实际上并非如此。

      

    1 function foo (){
    2     this.count ++;
    3 }
    4 foo.count = 0;
    5 for(var i=0;i<5;i++){
    6     foo();
    7 }
    8 console.log(foo.count);

        上面的例子旨在使用函数的this指向this,通过foo函数的count属性计算foo被调用的次数。根据这个目的,输出应该是5,因为for循环了五次,foo函数被调用了5次。但实际上呢?

        我们新建一个js文件,命名为test.js,代码如下:

        实际输出如下:

        输出的foo.count值为0。看上去foo中的this并没有指向foo,那么this指向了哪里呢?

      

        通过chrome JavaScript调试器可以发现,this指向了window全局作用域,并没有如我们预期的指向foo本身。

      误会(二):this指向函数所在作用域

        通过上面的例子,可能你很快就能得出结论:this指向所在函数所在的作用域。比如上一个例子中,函数foo位于全局作用域(在宿主环境中就是window),foo中的this便指向了全局作用域,但是果真如此吗?

        

     1 function foo (){
     2     var count = 0;
     3     function bar (){
     4            this.count ++;
     5     }
     6     for(var i=0;i<5;i++){
     7            bar();          
     8     }
     9     return count;
    10 }

        上面的代码,旨在foo内部,声明一个bar函数用于控制foo作用域内的count变量,实现计算bar被调用次数的功能。理论上,bar函数中的this应该会指向bar所在的作用域,所以this也可以调用count(和bar函数同作用域),应该输出为5。但实际输出呢?

        实际输出仍然为0!说明this根本没有指向bar所在的作用域,那么this指向哪了呢?

        实际上,this还是指向了window作用域,真是非常神奇。

        要想了解this的工作方式,我们先了解一下this的绑定方式。

    2.this的绑定规则

       (1)默认绑定

          当函数独立调用时,这条规则就是无法应用其他规则时的默认规则。

           直接使用不带任何修饰的函数,this会指向全局环境。

            

    1 function foo (){
    2      this.count = 100;
    3 }
    4 foo();         //直接使用,函数未经修饰
    5 console.log(window.count);       //输出全局环境中的count变量,就是函数中的this.count,结果为100

            但是this不总是指向全局环境,当使用严格模式时,this会被禁止指向全局环境。

    1 function foo (){
    2      "use strict";    //使用严格模式
    3      this.count = 100;
    4 } 
    5 foo();
    6 console.log(window.count);  //输出:Uncaught TypeError: Cannot set property 'count' of undefined

        (2)隐式绑定:

           

    1 function foo (){
    2      console.log(this.count);
    3 }
    4 var obj = {
    5      count:100,
    6      foo:foo
    7 };
    8 obj.foo();    //输出100

            当所调用的函数是某个对象的成员函数时,函数中的this会指向函数所在的对象。

            隐式绑定可能会存在绑定丢失的场景,当函数作为参数传入到另外一个函数时,作为参数的函数所绑定的this会失效。

     1 function foo(){
     2      console.log(this.count);
     3 }
     4 function bar (func){
     5      func();
     6 }
     7 var count = 0;
     8 var obj = {
     9      count : 100,
    10      foo : foo
    11 };
    12 bar(obj.foo);      //会输出0

            如上例,当obj.foo作为参数传入到函数bar时,原来绑定的this指向obj被修改为指向全局变量window。所以使用回调函数,可能会修改传入参数函数的this指向。

        (3)显式绑定

           使用call()或者apply()函数可以显式强制的绑定函数的this。

            

    function foo (){
         console.log(this.count);
    }
    var count = 'window!';
    var obj1 = {
         count : 100,
         foo : foo
    };
    var obj2 = {
         count : 200,
         foo : foo
    };
    foo.call(obj1);   //输出100
    foo.call(obj2);   //输出200

            如上例所示,call两次修改了foo的this指向。使其指向某个固定的对象。当call的传入的第一个参数为null时,所修改函数的this指向不会被显式修改。

         (4)new 绑定

             使用new操作符,可以将函数的this指向新创建的对象。

           

    function Foo(name, age){
         this.name = name;
         this.age = age; 
    } 
    var obj = new Foo('Tom',99);
    console.log(obj);

            输出如下:

              新构建的obj对象具有了一系列属性,都是用函数Foo中的this所实现。

            通过这个原理,我们可以简单的实现一个_new_函数,以实现new操作符的功能。

             

    function _new_ (func , arr){
        var obj = {};
        func.apply(obj,arr);
        return obj;
    }
    function Foo (name, age){
        this.name = name;
        this.age = age;
    }
    var obj = _new_(Foo,['Jerry',99]);
    console.log(obj);

             输出的obj如下:

            说明基本的传参构造对象功能已经实现了。

     

    3.四种绑定规则的优先级

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

        判断this绑定的顺序:

          1.判断是否是new调用,是的话就是new绑定,函数中的this会指向新构造的对象。

              2.判断是否是显示绑定,即是否是通过函数原型中的apply方法或者call方法调用 (还要注意bind返回的函数,this指向也会被修改)。

              3.判断是否是隐式绑定,及通过某个对象调用。是的话,this会指向所属对象。

              4.如果都没有的话,就是默认绑定,this指向全局对象window;严格模式下指向undefined。

    ……更过this相关,有待补充,如有错误,欢迎指正!

      

  • 相关阅读:
    多进程之数据安全问题
    windows 下安装 RabbitMQ
    springCloud Config分布式配置中心
    git配置ssh
    spring cloud Gateway 新一代网关
    spring cloud Hystrix 断路器
    spring cloud OpenFeign 服务接口调用
    Ribbon负载均衡服务调用
    consul服务注册与发现
    Eureka服务治理
  • 原文地址:https://www.cnblogs.com/DM428/p/7515818.html
Copyright © 2011-2022 走看看