浅谈-this

浅谈-this

this简单而又神秘,使用场景多变而又复杂,这造就了它成为了初级javascript开发人员不肯接触的东西,高级javascript都想探究的东西。文本亦是对this的致敬。javascript

  1. this是什么?
    this是当前执行环境的上下文,一般由函数的调用方式决定其值。
  2. this的原理java

    首先,从函数的调用开始node

    函数的调用通常有三种状况(ES5中)数组

    1.foo(p1,p2);
    2.obj.foo(p1,p2);
    3.foo().call(context,p1,p2);//或者apply

    一般状况下,大部分童鞋经常使用的都是前两种方式,只有在不得不绑定context的状况下才会使用第三种。其中,第三种方式,才是函数调用的正确方式。浏览器

    foo().call(context,p1,p2);

    之因此,咱们在使用前两种方式也能正常的运行,这其实就是一种语法糖而已,在js运行机制中,会把前两种调方式,当作下面的方式进行处理闭包

    foo(p1, p2) 等价于  
    foo.call(undefined, p1, p2)
    
     obj.foo(p1, p2) 等价于
     obj.foo.call(obj, p1, p2)

    所以,若是咱们之后再调用函数时,能准确的找到context,就能够惟一的确认this的值app

  3. this的使用场景
  • 3.1 全局环境使用函数

    不管是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象。
    // 在浏览器中, window 对象同时也是全局对象:
    console.log(this === window); // true
    var a=1;
    console.log(this.a) //1
    console.log(window.a) //1
  • 3.2 普通函数中调用this

    在非严格模式下,且this的值没有被调用函数设置,this 的值默认指向全局对象。
    funnction func(){
         console.log(this)
       }
       //浏览器环境中
       func()  // window
       //node环境中
       func()  // global
    在严格模式下,this的值若是不设置,就是是undefined
    funnction func(){
         "use strict"
         console.log(this)
       }
      func() === undefined; // true
  • 3.3 做为对象中的方法调用prototype

    var obj={

    name:'我是对象obj',
        ofun:function(){
        console.log(this.name)
        }
    }
    var name='我是全局name';
    var func= obj.ofun;
    obj.ofun(); //我是对象obj
    func(); //我是全局name

    这里有两点须要注意:

    1.函数做为对象的方法进行调用时,this指向当前的对象。                  
       2.对象中的函数方法名存储的仅是一个函数的地址(地址中会有该函数的属性:[[value]、[[writable]]、[[enumerable]]、[[congifable]])
       当把一个对象的方法赋值给另外一个变量(例如:func)时,引擎会将函数单独保存在内存中,而后再将函数的地址赋值给foo属性的value属性。
  • 3.4 构造函数中使用

    this在构造函数中使用,值为实例化的对象
    function Fun(name){
         this.name=name;
         this.speak=function(){
            console.log(this.name);
         }
       }
       var fun1=new Fun('jack');
       fun1.speak();
       var fun2=new Fun('rose');
       fun2.speak();//rose
  • 3.5 bind/call/apply

    this再被bind/call/apply强制绑定上下文执行环境时,属于硬绑定。
    function foo(somerthing){
         console.log(this.a);
       }
       var obj={
         a:2
       }
       var bar = function(){
         foo.call(obj);
       };
       bar(); //2
       //硬绑定的bar不可能再修改它的this
       bar.call(window);//2
     }

    硬绑定的典型应用场景就是建立一个包裹函数,传入全部的参数并返回接收到的全部值;

    function foo(somerthing){
         console.log(this.a,something);
         return this.a +something;
       }
       var obj={
         a:2
       }
       var bar = function(){
         return foo.apply(obj,arguments);
       };
       var b=bar(3);// 2 3
       console.log(b);//5

    因为硬绑定是一种很是经常使用的模式,因此在ES5中提供了内置的方法Function.prototype.bind,它的用法以下;

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

    call,apply,bind方法的区别:

  a:第一个参数都是要绑定的上下文执行环境,即this的值。
  b:均可在函数调用时传递参数。call,bind方法须要直接传入,而apply方法须要以数组的形式传入。
  c:call,apply方法是在调用以后当即执行函数,而bind方法没有当即执行,须要将函数再执行一遍。有点闭包的味道。
  d:改变this对象的指向问题不只有call,apply,bind方法,也可使用that/self等变量来固定this的指向。

  • 3.6 回调函数中调用

    在回调函数中通常有两种状况:
       1. 回调函数为匿名函数时,回调函数的this会指向window,须要对回调函数bind(this)。
       2. 回调函数为箭头函数时,回调函数的this会指向他的直接上层。
var obj = {
      name: "test for call-func",
      ofun: function(){
            //undefined 丢失
            setTimeout(function(){
              console.log(this.name)
            }, 100);
           //work well 硬绑定
            setTimeout(function(){
               console.log(this.name)
            }.bind(this), 100);//test for call-func
           // arrow function  test for call-func
           setTimeout( () => console.log(this.id), 100)
      }
    };

    obj.ofun();
  • 3.7 自执行函数
    自执行或者当即执行函数中的this指向Window
    首先自执行函数的几种调用方式

    //常见的有两种:
    (function(){})()    (function(){}())//w3c推荐方式
    //只有表达式才能被执行符号()执行
    +function test(){}();//+ - ! =等运算符可使前面的函数成为表达式,加上后面()可当即执行。
    //函数声明没法当即执行一个函数,可是函数表达式能够
    var a = function(){}();//这种是函数表达式,后面有()能够当即执行。成为一个当即执行函数。
    var obj = {
        number: 3,
        xxx: (function () {
            console.log(this + '--')//当即执行函数中的this指向window,由于当即执行函数是window调用的
            console.log(this.number + '~~~')//删除上面一行,此处this.number返回undefined
            return function () {
                console.log(this.number + '】')
                this.number += 7;
                console.log(this + '+')
            }
        })()
    }
    
    obj.xxx() //至关于obj.xxx.call(),因此此处的this指向obj
    console.log(obj.number) //10
相关文章
相关标签/搜索