this的指向问题(this指向一般谁调用它,它就指向谁)
- 全局执行上下文中,非严格模式下this指向window,严格模式下this指向undefined,在node.js中this指向global
console.log(this); // 在浏览器中输出 window 对象
- 函数调用(此时函数不是作为一个对象的属性,是直接函数来调用的)
当为普通函数时,this指向window,严格模式下指向undefined
当函数为箭头函数时,绑定的是父作用域的this指向
function example() {
console.log(this); // 非严格模式下输出 window,严格模式下输出 undefined
}
example();
- 当一个函数作为一个对象的方法来调用的时候,this指向这个对象,同样箭头函数除外,它会捕获其所在上下文的this
const obj = {
name: 'Object Name',
greet: function() {
console.log('Hello, ' + this.name);
}
};
obj.greet(); // 输出: Hello, Object Name
- 构造函数中的this,使用new关键字创建对象时,this在构造函数中指向新创建的对象
function Person () {
console.log(this)
this.name = '妹妹'
}
var obj = new Person() // 得到一个实例化对象,继承了Person函数的属性
console.log(obj)
- 事件中的this,在事件处理中this通常指向触发事件的元素
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this); // 输出: button 元素
});
- apply、call、bind中的this,apply和call改变的是函数运行时的this的指向,bind返回一个this绑定了传入对象的新函数。这个函数的this指向使用new时会被改变,直接使用该函数this指向传如的对象。
const obj = { name: '妹妹', age: 18 }
function Person () {
console.log(this.name)
}
Person.apply(obj)
Person.call(obj)
Person.bind(obj)
- 箭头函数,箭头函数没有自己的this上下文,它会捕获其所在上下文的this的值,作为自己的this的值
const obj = {
name: 'Object Name',
greet: () => {
console.log('Hello, ' + this.name);
}
};
obj.greet(); // 箭头函数中的 this 指向全局对象或undefined(严格模式)
- setTimeout,setInterval中的this
全局中
function timer() {
console.log(this);
}
setTimeout(timer, 1000); // 在浏览器中,this 指向 window 对象
在对象方法中这里又要分两种情况了 ,定时器内的函数参数是否使用了箭头函数
const obj1 = {
timerMethod: function () {
console.log(this); // 在方法中,this 指向 obj1
setTimeout(function () { // 注意这里使用的是普通函数如果是箭头函数就会不同
console.log(this); // this 指向全局对象,而不是 obj1
}, 1000);
}
};
obj1.timerMethod();
const obj2 = {
timerMethod: function () {
this.value = 'Hello';
setTimeout(() => { // 此时这里是箭头函数,它没有this,它会捕获其所在上下文的this值,箭头函数的this将与定义箭头函数this的上下文相同
console.log(this.value); // 正确地访问到 this.value,输出 'Hello'
}, 1000);
}
};
obj2.timerMethod();
const obj3 = {
value: 'Hello',
timerMethod: function () {
setTimeout(function () { // 这里的参数是普通函数我们可以使用call、apply改变this的指向
console.log(this.value); // this 指向 obj
}.call(this), 1000);
}
};
obj3.timerMethod();
const obj4 = {
value: 'Hello',
timerMethod: function () {
setTimeout( () => {
console.log(this.value); // this 指向 obj
}.call(this), 1000);// 这里就不能这样使用 会直接报代码错误的
}
};
obj4.timerMethod();
总结:
- 全局作用域中的this指向window
- 普通函数this指向window,箭头函数指向它的上下文this
- 对象中方法的this指向该方法所属的对象
- 构造函数中的this指向实例出来的对象
- 事件当中的this指向当前绑定的元素
- 定时器中的this指向,需要根据定时器的函数参数是否是箭头函数再进行判断
- apply 、call 和 bind 调用中的this指向它想要指向的this
箭头函数与普通函数的区别
- 语法简洁 () => {}
// 普通函数
const add = function(x, y) {
return x + y;
};
// 箭头函数
const add = (x, y) => x + y;
- this上下文
1、箭头函数不会创建自己的this上下文,它会捕获其所在上下文的this值,作为自己的this值,并且这个this值是不可更改的。即使使用apply call bind 都是不能更改的
2、普通函数的this值在每次调用时都会重新确定,通常指向调用它的对象,除非使用call、apply或bind方法。
const obj = {
name: 'Alice',
greet: () => console.log(`Hello, ${this.name}`), // `this`指向全局对象或undefined(严格模式)
};
obj.greet(); // 如果在严格模式下,将输出 undefined
- 箭头函数不能用作构造函数,意思不能使用new关键字来调用箭头函数,因为箭头函数没有prototype属性,在指向new操作时,我们需要将构造函数的原型赋值给实例对象的原型。
- argument对象 箭头函数中没有自己的arguments对象,如果需要访问函数的参数,可以使用剩余参数(rest parameters)代替。
// 普通函数
function foo() {
console.log(arguments);
}
// 箭头函数
const foo = (...args) => {
console.log(args);
};
- 箭头函数不能作为生成器函数,也就是说,不能在其内部使用yield关键字
const gen = () => {
yield 1; // 语法错误
};
总结
1、箭头函数没有this,它会捕获上下文的this,作为自己的this值,该值任何方法都不能更改的。
2、箭头函数没有原型对象,所以不能进行new实例化对象,当然就不能做构造函数
3、箭头的函数没有arguments对象,可以使用剩余参数代替
4、语法简洁,不能作为生成器函数