在我们日常开发中,this基本上无处不在,类似vue中的this。其实,在javascript中,this的指向问题还算得上是一个难点。其根本原因就是this指向在不同的场景下,指向的东西都是不一样的。
this指向可以分为几个场景:
其实很好理解,如果在全局中使用this,则指向全局对象window
如果在函数中使用this,就要根据函数是如何被调用的来确定this的指向
1、如果是全局调用,则指向window
function fn(){
console.log(this); // window
}
fn() // 此时的函数调用等于全局调用,等价于window.fn()
也可以理解为,一般的函数调用,this指向的是window
2、函数被对象调用,或者调用对象内的this,指向对象本身
let obj ={
fn(){
console.log(this); // 指向ob本身j
}
}
注意:如果在严格模式下,就绑定到undefined,否则绑定到全局对象
3、如果是构造函数,则this指向当前new出来的实例对象
function Foo(name){
this.name = name
console.log(this); //Foo
}
let o = new Foo('xiaoming')
console.log(o.name); //指向构造函数new出来的实例
4、如果是用call、apply或者bind调用,则可以改变你的this指向
- call()方法
语法:call(fn,obj,...args)
功能: 执行fn,使this为obj ,并将后面的n个参数传给等同于函数对象的call方法
- apply()方法
语法:apply(fn,obj,args)
功能:执行f,使this为obj,并将args数组中的元素传给fn(功能等同于函数对象apply方法)
- bind()方法
语法:bind(fn,obj,...args)
功能:给fn绑定this为obj,并指定参数为后面的n个参数(功能等同于函数对象的bind方法)
5、箭头函数中的this是根据其声明的地方来决定this的,箭头函数无法通过call、apply、bind修改,而且因为箭头函数没有constructor,所以也不能使用new调用,即不能作为构造函数,否则会报错
总结
一、this在全局中指向window
二、this在函数中指向具体看函数如何被调用
1.如果是普通函数调用,this指向window
2.如果是构造函数,也就是通过new调用,this指向构造函数当前new出来的实例
3.函数是否在某个上下文对象中调用,是的话,this绑定的是那个上下文对象,如果都不是,使用默认绑定,如果在严格模式下,就绑定到undefined,否则绑定到全局对象
4.如果是call、apply或者bind调用,this就指向你手动在call、apply或者bind后面设置的对象
5、箭头函数中的this是根据其声明的地方来决定this的,箭头函数无法通过call、apply、bind修改,而且因为箭头函数没有constructor,所以也不能使用new调用,即不能作为构造函数,否则会报错
另外,我们也可以尝试封装一下call、apply、bind三个方法
// 封装函数call()
function call(Fn, obj, ...args) {
// 注意:this可能不是该方法看到的实际值
//如果这个函数处于非严格模式下,则指定为null或undefined时会自动替换为指向全局对象,原始指会被包装
if (obj === undefined || obj === null) {
obj = globalThis; //全局对象
}
obj.temp = Fn
let result = obj.temp(...args);
delete obj.temp
return result
}
// 封装 apply()函数
function apply(Fn, obj, args) {
// 首先判断,obj是什么值
if (obj === undefined || obj === null) {
obj = globalThis
}
obj.temp = Fn
let result = obj.temp(...args)
delete obj.temp
return result
}
// 封装bind()函数
function bind(Fn, obj, ...args) {
return function (...args2) {
return call(Fn, obj, ...args, ...args2)
}
}