今天在学习过程中碰到了一个bind与call和apply这三种显示绑定的方法有什么区别,于是呢就想写篇这个有关this指向的文章
引言
在JavaScript中,this关键字是一个重要且复杂的概念。而且也是在面试时,面试官会经常拿出来考察我们对JS基础知识是否合格的一个点。this关键字可以根据函数的调用方式指向不同的对象,使得它在编写代码时既灵活又具有挑战性。理解this的指向可以显著提升代码质量,减少上下文参数的传递,增强代码的可读性和可维护性。那么直接来聊一聊this的几种指向规则吧
this 的指向规则
默认绑定
默认绑定是指当一个函数独立调用时(即不带任何修饰符的调用),
this指向全局对象。在浏览器中,全局对象是window。在Node.js中则是指向global。
// 非严格模式
function sayHello() {
console.log(this === window); // true
}
sayHello();
// 严格模式
"use strict";
function sayHelloStrict() {
console.log(this); // undefined
}
sayHelloStrict();
如果是在严格模式下,this 将不会被绑定到任何特定的对象。相反,它会被设置为 undefined。
隐式绑定
当一个函数被某个对象所拥有,或者函数被某个上下文对象调用时,该函数中的
this指向该上下文对象。
const obj = {
name: 'Alice',
getName: function() {
console.log(this.name);
}
};
obj.getName(); // 输出 'Alice'
隐式丢失
当一个函数被多个对象链式调用时,this指向最近的那个对象。或者在某些情况下,即使函数被作为对象的方法调用,
this可能会失去其预期的绑定,尤其是当函数被赋值给一个变量或以其他方式间接调用时。
两个例子:
var obj1={
name:"Alice",
obj2:{
name:"Bob",
getName:function () {
console.log(`Hello ${this.name}`);
}
}
}
obj1.obj2.getName() // 输出'Hello Bob'
const obj = {
name: 'Alice',
getName: function () {
console.log(`Hello, ${this.name}`);
}
};
const getName = obj.getName;
getName(); // 输出:Hello, undefined (非严格模式) 或 抛出错误 (严格模式)
隐式丢失和隐式绑定这两种情况总结来说就是谁调用this就☞向谁。
显示绑定
有三种方法 call apply bind都是能指定this的指向,比较强硬。但是他们的用法还是有点区别的
call
call 方法接受的第一个参数是 this 应该指向的对象,随后的参数则是函数应该接收的参数列表。
var obj={
a:1
}
function foo(x,y){
console.log(this.a,x+y);
}
foo.call(obj,1,2) // 输出1 3
apply
apply的方法与call相似,第一个参数是指向的对象,随后的参数都是用数组的方式添加。
var obj={
a:1
}
function foo(x,y){
console.log(this.a,x+y);
}
foo.apply(obj,[2,3]) // 输出1 5
bind
call和apply都可以立即调用函数,但call接受参数列表,而apply接受一个参数数组。bind方法创建并返回一个新的函数,在调用这个新函数时,this被绑定到bind方法的调用者所指定的对象。这意味着使用bind创建的新函数将始终以指定的this值进行调用,无论后续如何调用该函数。
最主要的区别还是在执行时机上,
bind返回一个新的函数,不立即执行;call和apply立即执行函数。
var obj={
a:1
}
function foo(x,y){
console.log(this.a,x+y);
}
const bar=foo.bind(obj,1,2)
bar(1,2) // 输出1 3
new 绑定
当使用 new 关键字调用构造函数时,构造函数内的 this 会绑定到新创建的对象实例。
function Person(){
this.name='Alice'
}
let p=new Person()
console.log(p.name); // 输出Alice
可以看下前端面试js系列:手写new - 掘金 (juejin.cn)这篇手写new可能会更容易理解
箭头函数
箭头函数并没有自己的 this 值。它们继承自定义箭头函数的最近一层非箭头函数的作用域的 this 值。
var obj={
a:1,
foo:function(){
const fn=()=>{
console.log(this.a);
}
fn()
}
}
obj.foo()
这段代码箭头函数里的this就是继承离它最近的foo函数的this,然后foo作为 obj 的一个方法被调用的。