JavaScript中this机制设计的原因及其规则

63 阅读2分钟

1. JavaScript中为什么要有this机制?

#include <iostream>
   using namespace std;
   class Bar{
       public:
       char* myName;
       Bar(){
         myName = "冰淇淋";
       }
       void printName(){
          cout<< myName <<endl;
       }  
   } bar;

   char* myName = "抹茶";
   int main() {
     bar.printName();
     return 0;
   }

在这段 C++ 代码中,调用了 bar 对象中的 printName 方法,最后打印出来的值就是 bar 对象的内部变量 myName 值——“冰淇淋”,而并不是最外面定义变量 myName 的值——“抹茶”,所以调用对象内部的方法中,使用的是对象内部的属性,是一个非常普遍的需求。但是 JavaScript 的作用域机制并不支持这一点,基于这个需求,JavaScript 又搞出来另外一套 this 机制。

2. this绑定的规则

this绑定规则主要有四种,如下所示

1.默认绑定

this没有指明绑定的对象,默认指向全局对象(客户端 JavaScript 中,全局对象就是 Window 对象)

    function foo(){
        console.log('foo函数:'+this.a);
    }
    var a=2;
    foo();
    console.log('全局对象:'+window.a);

image.png

2.隐式绑定

当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象。

对象属性引用链中只有上一层或者说最后一层在调用位置中起作用 使用对象来调用其内部的方法,其this指向的是对象本身。

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

    var obj1={
        a:2,
        obj2:obj2
    };

    obj1.obj2.foo();

image.png

3.显示绑定

使用call(...),apply(...),bind(...)方法,直接指定this的绑定对象,称之为显式绑定


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

image.png

4. new绑定

JavaScript 中,构造函数只是一些使用new 操作符被调用的函数 包括内置对象函数在内的所有函数都可以用new来调用,这种函数调用被称为构造函数调用

使用new来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。

  1. 创建(或者说构造)一个全新的对象
  2. 这个新对象会被执行[[Prototype]]连接
  3. 这个新对象会绑定到函数调用的this
  4. 如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个对象

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

image.png

3. 优先级

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