javascript 中this 的理解以及call、apply、bind 函数用法
注意:下面的js代码并未嵌入html后的运行结果,而是直接通过node执行js脚本运行代码得到的结果,(两种运行方式得到结果有所不同)
this的指向性问题
首先通过一个案例引入this的指向性问题
案例一
var name = "小王" ,age = 17;
var obj = {
name : "小李",
objAge: age,
myFun(){
console.log(this.name + '年龄' + this.age);
}
}
console.log(obj.objAge)
obj.myFun()
通过分析输出的结果,其中的obj.myFun() 执行的时候输出"小李年龄undefined" ,也就是说 obj.myFun() 函数中的this 也就是obj这个实例对象,为证明这个说法我们修改上述的代码。 案例二
var name = "小王" ,age = 17;
var obj = {
name : "小李",
objAge: age,
myFun(){
console.log(this === obj)
console.log(this)
}
}
obj.myFun()
通过修改后的代码,通过输出结果可以发现,obj.myFun() 这个函数中所指的this 就是obj 这个对象。
注意上述myFun 都是通过function的方式去声明数组的,若是箭头函数this的指向则会不同, 下面通过案例来展示箭头函数中this指向的不同
我们直接上代码看具体的案例
案例三
var name = "小王" ,age = 17;
var obj = {
name : "小李",
objAge: age,
myFun:() => {
console.log(this)
}
}
obj.myFun()
可以看到这个案例中,只是将obj中原来的myFun这个函数的声明从function改成了用箭头函数的声明方式,但是this 的指向却从原来指向的obj这个实例对象变成了**{}** 这个空对象(通过嵌入html代码中运行的话输出的windows这个对象),这是因为箭头函数中的this会找到找到当前对象的上一层,同样的我们通过一个案例证明。
案例四
var obj2 = {
name: "小池",
myFun(){
const test = () => {
console.log(this)
console.log(this === obj2);
}
test();
}
}
obj2.myFun()
可以看到我们在myFun这个函数中声明了一个箭头函数,由于test函数是通过箭头函数声明的,其内部的this会向外找一层也就是myFun这个函数所对应的this结合输出结果与上述的案例二中的结果相符合。
那么this的指向可以发生改变吗?怎么改变它?
案例五
var name = "小王" ,age = 17;
var obj = {
name : "小李",
objAge: age,
myFun(){
console.log(this.name + "年龄" + this.age)
}
}
var obj2 = {
name: "小池",
age,
}
obj2.myFun = obj.myFun
obj.myFun()
obj2.myFun()
可以看到通过obj2访问到的myFun中的this又指向了obj2,obj2.myFun = obj.myFun 可以理解成在obj2上写了一份myFun函数
使用 call、apply、bind 函数
案例六 不传参
var name = "小王" ,age = 17;
var obj = {
name : "小李",
objAge: age,
myFun(){
console.log(this.name + "年龄" + this.age)
}
}
var db = {
name: "德玛",
age: 99,
}
obj.myFun.call(db);
obj.myFun.apply(db);
obj.myFun.bind(db)();
可以看到在这个案例中,call 、apply、bind 函数都将obj.myFun 函数中的this指向为db 而此时这三个函数的用法几乎相同,call、apply 函数可以直接帮你修改其中的this指向并且同时调用,而bind在修改this的指向后返回的是一个函数。
案例七 传参
var name = "小王" ,age = 17;
var obj = {
name : "小李",
objAge: age,
myFun(mom, fat){
console.log(mom + "--" + fat)
}
}
var db = {
name: "德玛",
age: 99,
}
obj.myFun.call(db,"A","B");
obj.myFun.apply(db,["A","B"]);
obj.myFun.bind(db,"A","B")();
obj.myFun.bind(db,["A","B"])();
可以看到三个函数的传参方式有所不同
- call 函数,多个参数间直接用
"," 隔开 - apply函数,多个参数通过数组的形式传入
- bind函数,多个参数直接用
"," 隔开
总结
理解js中this 的指向还是很重要的,不然有时候会遇到一些坑,不如react中的用类写组件的方式就容易遇到这样的问题。
|