JS中this的指向

91 阅读3分钟

一、this在全局下指向什么?

  • 在浏览器中指向window
  • 在node中指向obj对象

二、this的基础规则

function foo() {
  console.log(this);
}
//1.直接调用
foo(); //Window

let obj = {
  name: "JAY",
  foo: foo,
};
//2.通过对象的方法来调用
obj.foo(); //Obj对象

//3.apply调用
foo.apply("abc"); //String {'abc'}对象

上述3种的不同调用方式,可以看出在函数中this的指向并不固定,那么它们到底遵循什么样的规则呢?

规则一、默认绑定

独立函数的调用,this指向的是window

  • 独立的函数调用我们可以理解成函数没有被绑定到某个对象上进行调用;
function foo() {
  console.log(this);
}

let obj = {
  name: "JAY",
  foo: function () {
    console.log(this);
  },
};
let bar = obj.foo;
bar(); //window

规则二、隐式绑定

  • 也就是它的调用位置中,是通过某个对象发起的函数调用。
let obj1 = {
  name: "obj1",
  foo: function () {
    console.log(this);
  },
};

let obj2 = {
  name: "obj2",
  bar: obj1.foo,
};

obj2.bar(); //obj2对象

规则三、显示绑定

  • 我们明确的绑定了this指向的对象,称之为 显示绑定
  • 显示绑定和隐式绑定冲突:显示绑定优先级高
  1. apply和call的显示绑定
// call和apply有什么区别
function sum(num1, num2) {
  console.log(num1 + num2, this);
}
sum.call("call", 1, 2); //3,String{'call'}
sum.apply("call", [1, 2]); //3,String{'call'}

2.bind的显示绑定

function foo() {
  console.log(this);
}
let newFoo = foo.bind("aaa");
newFoo(); //String {'aaa'}

规则四、new绑定

  • JavaScript中的函数可以当做一个类的构造函数来使用,也就是使用new关键字。
  • 使用new关键字来调用函数是,会执行如下的操作:
    • 创建一个全新的对象
    • 这个新对象会被执行prototype连接
    • 这个新对象会绑定到函数调用的this上(this的绑定在这个步骤完成)
    • 如果函数没有返回其他对象,表达式会返回这个新对象
// 我们通过调用一个new关键字调用一个函数(构造器),这个时候this是在调用这个构造器的对象
// this=创建出来的对象
// 这个绑定的过程就是new的绑定
function person(name) {
  console.log(this);
  this.name = name;
}
let p = new person("JAY"); // {}
console.log(p.name); // “JAY”

规则的优先级

  • 默认规则是最低的,因为存在其他规则时,会通过其他规则来绑定this

  • 显示绑定优先级高于隐式绑定

function foo() {
  console.log(this)
}

let obj = {
  name: "obj",
  foo: foo.bind("aaa")
}

obj.foo()//String {'aaa'}
  • new绑定优先级高于隐式绑定
let obj = {
  name: "obj",
  foo: function () {
    console.log(this);
  },
};

let f = new obj.foo();//foo {}
  • new绑定优先级高于bind
    • new绑定和call、apply是不允许同时使用的,所以不存在谁的优先级更高

    • new绑定可以和bind一起使用,new绑定优先级更高

    function foo() {
      console.log(this);
    }
    
    let bar = foo.bind("aaa");
    
    let obj = new bar(); //foo {}
    

this规则之外-忽略显示绑定

apply/call/bind:当传入null/undefined时,自动将this绑定成全局对象

function foo() {
  console.log(this);
}

foo.apply("abc"); //String {'abc'}
foo.apply({}); //{}
foo.apply(null); //Window
foo.apply(undefined); //Window

this规则之外-间接函数引用

let obj1 = {
  name: "obj1",
  foo: function () {
    console.log(this);
  },
};

let obj2 = {
  name: "obj2",
};

obj2.bar = obj1.foo;
obj2.bar(); //{name: 'obj2', bar: ƒ}

this规则之外-箭头函数

  • 箭头函数不使用this来的四种规则(也就是不绑定this),根据外层作用域来绑定