JS中this的几种指向

156 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

JavaScript 中 this 的指向主要有以下几种,关于 this 最核心的一句话:哪个对象调用函数,函数里面的 this 就指向哪个对象

1.普通函数调用:默认绑定

当一个函数并非一个对象的属性时,那么它就是被当做函数来调用的。这种情况 this 指向全局对象 window。

var firstName = "yuan"; // 这里用到了var会把变量定义在window对象上的特性,如果使用let或者const则不行
function fn() {
  console.log(this.firstName); // yuan
  console.log(this); // window
}
fn();

2.对象函数调用:隐式绑定

当函数被保存为一个对象的属性时,它就可称为这个对象的方法。这种情况哪个对象调用函数,函数中的 this 就指向哪个对象。

let obj = {
  firstName: "yuan",
  fn() {
    console.log(this);
    console.log(this.firstName);
  },
};
​
obj.fn(); // obj   yuan
// 充分诠释:哪个对象调用,函数中的this就指向哪个对象
​
let obj1 = {
  firstName: "yuan",
  fn() {
    console.log(this);
    console.log(this.firstName);
  },
};
​
let obj2 = {
  firstName: "jin",
};obj2.fn = obj1.fn;
​
obj2.fn(); // obj2     jin
let fn = function() {
  let firstName = "yuan";
  console.log(this.firstName);
};
​
let obj = {
  firstName: "jin",
  fn,
};
​
obj.fn(); // jin

3.apply、call、bind:显式绑定

javaScript 提供的绝大多数函数和自己创建的所有函数都有 call 和 apply 方法,这两种方法可以显式的将函数中的 this 指向他们所指定的对象。ES5 中提供了 bind()方法硬绑定。

注意: call 和 applay 方法的用途完全一样,只是传参的形式不一样而已

call()

语法:fn.call(obj,arg1,arg2,arg3...)

返回值:调用的 fn 函数的返回值。

let fn = function(firstName, lastName) {
  console.log(firstName);
  console.log(lastName);
  console.log(this.age);
};
​
let obj = {
  age: 112,
};
​
fn.call(obj, "yuan", "chengcheng"); // yuan  chencgheng  11

apply()

语法:fn.apply(obj,[arg1,arg2,arg3..])

返回值:调用的 fn 函数的返回值

let fn = function(firstName, lastName) {
  console.log(firstName);
  console.log(lastName);
  console.log(this.age);
};
​
let obj = {
  age: 112,
};
​
fn.apply(obj, ["yuan", "chengcheng"]); // yuan  chencgheng  11

bind()

语法:fn.bind(obj,arg1,arg2,arg3...)();

返回值:一个新的函数,必须调用它才会执行

let fn = function(firstName, lastName, place) {
  console.log(
    "姓" + firstName + "名" + lastName + "年龄" + this.age + "来自" + place
  );
};
​
let obj = {
  age: 112,
};
​
fn.bind(obj, "yuan", "cheng", "hubei")(); // 姓yuan名cheng年龄112来自hubei

4.构造函数调用:new 绑定

如果在一个函数前面加上 new 关键字来调用,那么就会创建一个连接到该函数的 prototype 成员的新对象,同时,this 会被绑定到这个新对象上。当使用 new 关键字返回一个对象,则 this 就指向这个返回的对象;

注意: 构造函数的命名通常需要首字母大写

let Person = function() {
  this.firstName = "yuan";
  this.obj = {
    age: 23,
    sex: "man",
  };
};
​
let one = new Person();
console.log(one); // Person

优先级

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

注意: ES6 中的箭头函数并不会使用这四条绑定规则,它是根据当前的词法作用域来决定 this,具体来讲,箭头函数会继承外层函数调用的 this 绑定(无论 this 绑定到什么)。