目录
- 一、前言
- 二、箭头函数
- 三、new指向
- 四、bind
- 五、call和apply
- 六、bind call apply区别
- 七、对象(obj.)
- 八、全局this指向
- 九、不在函数里
一、前言
JS 中 this 指向问题 - 掘金
在JavaScript中,this关键字表示当前执行代码的上下文对象。它的值取决于函数被调用的方式。this可以引用全局对象(在浏览器中是window对象),也可以引用当前对象(例如,在对象方法中),或者在使用构造函数创建对象时引用新创建的实例。
二、箭头函数
const obj = {
fun1: function () {
console.log(this);
},
fun2: () => {
console.log(this);
}
}
obj.fun1(); // obj
obj.fun2(); // window
- 箭头函数的 this 指向是在定义函数时确定的,而不是在运行时确定的。
- 箭头函数内的 this 指向外层的 this
- 箭头函数的 this 指向是无法改变的,即使使用 call、apply 或 bind 方法也无效。因此,在使用箭头函数时需要注意它的 this 指向。
三、new指向
// class Person {} 和 function Person(name, age) 都可以用来定义一个对象的构造函数,但它们有一些区别。
// 语法:class 是 ES6 中新增的语法,用于定义类和构造函数,而 function 是 JavaScript 中早期就存在的语法,用于定义函数和构造函数。
// 继承:class 支持更加简洁和灵活的继承方式,可以使用 extends 关键字来继承其他类,而 function 只能使用原型链来实现继承。
// 方法定义:在 class 中,方法可以直接定义在类的内部,而在 function 中,方法需要定义在构造函数的原型对象上。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
print() {
console.log(this);
}
}
const p1 = new Person('张三', 18);
p1.print()
- 当你使用new关键字调用函数的时候,函数中的this指向一定是实例对象
四、bind
const person = {
name: 'Alice',
age: 20
};
function sayHello() {
console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`);
}
const sayHello2 = sayHello.bind(person);
sayHello2(); // 输出 "Hello, my name is Alice, I'm 20 years old."
- 使用方法:bind(thisArg, arg1, arg2, /* …, */ argN)
- bind 方法是 JavaScript 中用于改变函数执行时 this 关键字指向的方法。它会返回一个新的函数,该函数与原函数具有相同的函数体,但是 this 关键字被绑定到指定的对象上。
- 需要注意的是,bind 方法不会修改原函数的 this 关键字,而是返回一个新的函数,但是不会立刻调用。同时,使用 bind 方法创建的新函数可以被多次调用,每次调用时都会使用相同的绑定对象,this不会被修改。
另外,bind 方法还可以用于实现函数柯里化(Currying),即将一个多参数函数转换为一个单参数函数序列的过程。例如:
function add(x, y) {
return x + y;
}
const add5 = add.bind(null, 5);
console.log(add5(3)); // 输出 8
console.log(add5(7)); // 输出 12
五、call和apply
const person = {
name: 'Alice',
age: 20
};
function sayHello() {
console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`);
}
sayHello.apply(person);
sayHello.call(person);
- call和apply都可以立即立即调用原函数,并且可以指定函数执行时的 this 关键字和参数列表
六、bind call apply区别
const name = '小王', age = 17
const obj = {
name: '小张',
objAge: this.age,
myFun: function (fm, t) {
console.log(this.name + '年龄' + this.age)
console.log(fm + t)
}
}
const db = {
name: '小李',
age: 18
}
obj.myFun.bind(db, '北京', '上海')()
obj.myFun.call(db, '北京', '上海')
obj.myFun.apply(db, ['北京', '上海'])
- 相同点:都会改变函数的this指向
- 绑定不同:
- bind不会改变原函数的this关键字,返回一个新的函数,不会立刻调用
- call、apply都可以立即调用原函数
- 传参不同:
- bind、call传入一组参数
- apply传入数组参数
七、对象(obj.)
function func() {
console.log(this.x)
}
obj = { x: 1 }
obj.func = func
obj.func() // 1
- 函数赋值给对象,当前this指向obj
- 如果是箭头函数会报错
八、全局this指向
function fn1 () {
console.log(this);
}
fn1() //window对象
九、不在函数里
不在函数中的场景,可分为浏览器的 script 标签里,或 Node.js 的模块文件里。
- 在 script 标签里,this 指向 Window。
- 在 Node.js 的模块文件里,this 指向 Module 的默认导出对象,也就是 module.exports。