0、总结:
1、是什么?
this 关键字是函数运行时自动生成的一个内部对象,只能在函数内部使用。
this的指向在函数定义的时候是无法确定的,只有函数执行的时候才能确定this指向谁。实际上this指向调用它的对象。
2、普通函数
2.1 非严格模式下,this指向window
function a() {
console.log(this);
}
a() // window
2.1 严格模式下,this指向undefined
注意:严格模式"use strict"要写到函数内部才会起效,写在函数外部依然指向window
function a() {
"use strict";
console.log(this);
}
a();
3、call apply bind
这三个方法都可以改变函数的this指向,除了箭头函数以外,箭头函数的this指向无法改变,这个问题在后续详细说。
面试题:三者的区别是什么?
回答:
1、三者都可以改变函数的this对象指向;
2、三者第一个参数都是this要指向的对象,如果没有这个参数或参数为undefined或null,则默认指向全局window;
3、三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入;
4、bind是返回绑定this之后的函数,需要自己再执行。而apply、call 则是立即执行。
3.1 不传参 / 传入null或者undefined,指向window
function fn() {
console.log(this);
}
fn.call(); // window
fn.apply(null); // window
let res = fn.bind(undefined);
res(); // bind返回一个函数,需要调用 //window
输出结果:
3.2 传参,指向传入的内容
function fn2() {
console.log(this);
}
fn2.call({
x: 101 }); // {x: 101}
fn2.apply("abc"); // String {'abc'}
fn2.apply(123); // Number {123}
let fn = fn2.bind({
name: "admin" });
fn(); // {name: 'admin'}
输出内容:
3.3 call() 和 apply() 的区别
第一个参数都是this的指向,
call 后面传入参数是一个参数列表,需要用逗号隔开
apply 第二个参数是函数接收的参数,以数组的形式传入
示例:
call():
function fn(...args){
console.log(this,args);
}
let obj = {
myname:"张三"
}
fn.call(obj,1,2); // 传入的参数用逗号隔开;
apply():
function fn(...args){
console.log(this,args);
}
let obj = {
myname:"张三"
}
fn.apply(obj,[1,2]); // 传入的参数必须是一个数组;
均输出为:
4、定时器
4.1 定时器 + function,this指向window
setTimeout(function () {
console.log(this);
}, 1000); // window
5、箭头函数
箭头函数没有自己的this,它的this是继承而来的;默认指向在定义它时所处的对象(宿主对象)
,此处指父级作用域
。
注意:箭头函数的this指向无法被call,applay,bind改变
,但可以通过改变它上一层对象的this指向来改变它的this指向
5.1 指向上层对象的this
此时的箭头函数的宿主对象是show(),而这个函数的执行需要被obj这个对象调用,所以show() 的this指向是对象obj,所以此时箭头函数的this从show继承而来,也就是对象obj
let obj = {
x: 123,
show() {
setTimeout(() => {
console.log(this);
}, 1000);
},
};
obj.show(); // {x: 123, show: ƒ}
obj.show.call({
x: 100 }); // 100 show()作为普通函数,它的this指向可以被call改变
5.2 指向window
此时的箭头函数的宿主对象是window,所以此处的this指向的是window
window.fn3 = () => console.log(this);
fn3();
输出: