注意:下面的js代码并未嵌入html后的运行结果,而是直接通过node执行js脚本运行代码得到的结果,(两种运行方式得到结果有所不同)
首先通过一个案例引入this的指向性问题
案例一
var name = "小王" ,age = 17;
var obj = {
name : "小李",
objAge: age, //
myFun(){ // 等价于 myFun:function myFun....这种写法
console.log(this.name + '年龄' + this.age);
}
}
console.log(obj.objAge)
obj.myFun()
//结果
//17
//小李年龄undefined
通过分析输出的结果,其中的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()
//结果
// true
// { name: '小李', objAge: 17, myFun: [Function: 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()
// 运行结果
// { name: '小池', myFun: [Function: myFun] }
// true
可以看到我们在myFun这个函数中声明了一个箭头函数,由于test函数是通过箭头函数声明的,其内部的this会向外找一层也就是myFun这个函数所对应的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()
// 运行结果
// 小李年龄undefined
// 小池年龄17
可以看到通过obj2访问到的myFun中的this又指向了obj2,
obj2.myFun = obj.myFun
可以理解成在obj2上写了一份myFun函数
案例六 不传参
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)();
// 结果
// 德玛年龄99
// 德玛年龄99
// 德玛年龄99
可以看到在这个案例中,
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"])();
// 运行结果
// A--B
// A--B
// A--B
// A,B--undefined
可以看到三个函数的传参方式有所不同
- call 函数,多个参数间直接用
","
隔开- apply函数,多个参数通过数组的形式传入
- bind函数,多个参数直接用
","
隔开
理解js中this 的指向还是很重要的,不然有时候会遇到一些坑,不如react中的用类写组件的方式就容易遇到这样的问题。