this是什么?

this 本质是一个绑定, 在函数被调用时建立。它的指向是完全由函数被调用的调用点来决定的。

function baz() {
    console.log(this);//因为baz函数的调用点在全局作用域,所以this指向全局变量
}
baz();//这里就是baz函数的调用点

this 存在的意义

在函数体内部指代函数当前的运行环境。从而实现干净的 API 设计和更容易的复用。

this的使用

  1. top-level scope

       1) In browsers, the top-level scope is the global scope. This means that within the browser var something will define a new global variable.In Node.js this is different. The top-level scope is not the global scope; var something inside a Node.js module will be local to that module. 
       2) 但是在Node REPL下,与浏览器的行为保持一致(timers除外)
           In browsers
               var that = this;
               setTimeout(function() {
                 console.log(this);//window
               }, 0);
            Node REPL
               var that = this;
               setTimeout(function() {
                 console.log(this);//Timeout {...}
               }, 0);   
           setInterval 结果相同
    
  2. 严格模式下

       指定的this不在被封装为对象,而且如果没有指定this,则this的值为undefined
       sloppy mode
           function foo() {
             console.log(this);
           }
           foo.apply("test"); //==>String {"test"}0: "t"1: "e"2: "s"3: "t"length: 4...[[PrimitiveValue]]: "test"
        strict mode    
           function foo() {
             "use strict";
             console.log(this);
           }
           foo.apply("test"); //==>test        
  3. 调用方法时没有明确对象,this指向全局对象

       sloppy mode
           In browsers,this指向window
               console.log(this);//window
           Node REPL, this指向global
               console.log(this);//global
       strict mode
           In browsers,this指向window
               "use strict";
               console.log(this);//window
           Node REPL, this指向global
               "use strict";
               console.log(this);//global            
  4. 匿名函数执行时当前对象是全局对象

       sloppy mode
           In browsers,
               (function() {
                 console.log(this);//window
               })();
           Node REPL
               (function() {
                 console.log(this);//global
               })(); 
       strict mode
           In browsers,
               (function() {
                 "use strict";
                 console.log(this);//undefined
               })();
           Node REPL
               (function() {
                 "use strict";
                 console.log(this);//undefined
               })(); 
    
  5. 强制一个函数调用使用某个特定对象作为 this 绑定,而不在这个对象上放置一个函数引用属性
    就 this 绑定的角度讲,call(..) 和 apply(..) 是完全一样的
    call

       function foo() {
         console.log(this.a);
       }
       var obj = {
         a: 2
       };
       foo.call(obj); //==>2 强制函数foo()的 this 指向 obj

    apply

       function foo() {
         console.log(this.a);
       }
       var obj = {
         a: 2
       };
       foo.apply(obj); //==>2 强制函数foo()的 this 指向 obj     
        
    bind 返回一个硬编码的新函数,它使用你指定的 this 环境来调用原本的函数
       function foo(something) {
         console.log(this.a, something);
         return this.a + something;
       }
       var obj = {
         a: 2
       };
       var a = 6;
       var bar = foo.bind(obj);//使用obj作为this环境调用foo()
       var b = bar(3); // 2 3
       console.log(b); // 5
       var test = bar.bind(window);//2 3 
       console.log(test(3)); // 5
       

    传递 null 或 undefined 作为 call、apply 或 bind 的 this 绑定参数,那么这些值会被忽略掉。

       sloppy mode
           function foo() {
             console.log(this);
           }
           var obj = {};
           foo.call(null);//window or global
           foo.apply(null);//window or global
           var bar = foo.bind(null);
           console.log(bar());//window or global
        strict mode
           "use strict";
           function foo() {
             console.log(this);
           }
           var obj = {};
           foo.call(null);//null
           foo.apply(null);//null
           var bar = foo.bind(null);
           console.log(bar());//null        
  6. new

       将新构建的对象被设置为函数调用的 this 绑定
       function foo(a) {
         console.log(this);
         this.a = a;
       }
       var bar = new foo(2);//构建了一个新的对象(foo {a: 2})并把这个新对象作为 foo(..) 调用的 this
       console.log(bar); //foo {a: 2}
       console.log(bar.a); // 2
       
  7. arrow functions

       箭头函数从封闭它的(函数或全局)作用域采用 this 绑定
       function foo() {
         // 返回一个箭头函数
         return (a) => { //箭头函数在词法上捕获 foo() 被调用时的 this(obj1)
           // 这里的 `this` 是词法上从 `foo()` 采用的
           console.log(this.a);
         };
       }
       var obj1 = {
         a: 2
       };
       var obj2 = {
         a: 3
       };
       var bar = foo.call(obj1);
       bar.call(obj2); //2
       
       

Refer:

  https://github.com/CuiFi/You-Dont-Know-JS-CN
  https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this

ocean
4 声望1 粉丝