本文已参与「新人创作礼」活动,一起开启掘金创作之路。
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 绑定到什么)。