本文已参与「新人创作礼」活动,一起开启掘金创作之路。详情
this的几种情况
this是存在于作用域对象中的一个关键字,this本身不是作用域。作用域只分为全局作用域和函数作用域。
判断this指向:一定不要看在哪里定义。一定只看将来在哪里,如何被调用。
1. obj.fun()
obj.fun()调用时,fun函数中的this指向obj对象
2. new
new一个构造函数,this指向new出来的新对象
3. 原型对象上方法中的this
构造函数.prototype.fun= function(){}
时,fun函数中的this指向调用fun的子对象:谁调用指向谁
以上三种this在这篇文章中有详细讲解:# 浅谈javascript面向对象三大特点,通过面向对象看原型原型链
4. 直接调用
fun()
、匿名函数自调
、回调函数
中的this指向window(严格模式(use strict)下,this指向undefined 因为这类函数调用时,前边即没有.
,也没有new!)
5. DOM事件的处理函数
如button.onclick=function(){}
、button.addEventListener(“click”,function(){…})
之类的事件函数中的this,指向当前的DOM元素对象。
6. Vue中
vue的this默认指向当前Vue对象
```js
<button@click=”fun”>
export default{
//vue中methods中的方法中的this默认都指当前vue组件对象
methods:{
fun(e){ e.target }
//如果想获得当前出发事件的DOM元素对象,必须用$event关键字和e.target联合使用
}
}
```
7. 箭头函数
箭头函数中的this是当前箭头函数之外最近的作用域的this
- 几乎所有的匿名函数都可用箭头函数简化
- 箭头函数是大多匿名函数的简写
// 关于箭头函数和普通函数的this区别
var lilei={
name:"Li Lei",
friends:["涛涛","楠楠","东东"],
intr:function(){
this.friends.forEach(function(元素值n){
console.log(`${this.name}认识${元素值n}`)
})
}
}
lilei.intr(); // 输出结果: undefined认识涛涛 undefined认识楠楠 undefined认识东东
// 解析:intr的方法中的this指向调用该方法的对象lilei
// 所以this.friends得到了lilei.friends
// 当this.friends循环遍历时,forEach中接收的回调函数没有人调用它,所以它里面的this指向window,访问this.name时就是undefined了。
// 把forEach中接收的回调函数改成箭头函数:
lilei.intr = function(){
this.friends.forEach((元素值n)=>{
console.log(`${this.name}认识${元素值n}`)
})
}
lilei.intr(); // 输出:Li Lei认识涛涛 Li Lei认识楠楠 Li Lei认识东东
// 改成箭头函数后,箭头函数的this是指向它自己外面最近的作用域的this
// 也就是和intr这个函数作用域的this指向相同,即指向lilei这个对象
// 此时的this.name就取到了lilei.name。
【注】如果上面案例中,intr方法的普通函数改成箭头函数的话,此时this.friends为undefined了,因为箭头函数指向intr外的作用域,即lilei对象外的作用域,也就是指向window了。
结论
①:在使用this时,如果希望函数内外的this保持一致,就可以使用箭头函数;
②:当不希望函数内外的this指向一样的时候,就不能用箭头函数。
【注】箭头函数只是改变了自身的this指向,不影响自身的局部变量作用域。箭头函数内部定义的变量仍是局部变量,只能在箭头函数内使用,在箭头函数外部无法访问该变量。
箭头函数的底层原理和bind的效果一样
8. 改变this的方法
-
call:①使用call会立即调用函数;②函数中this指向call的第一个参数;③call接收两个以上实参,可以将第二个及以后的参数传给函数
-
apply:①使用apply会立即调用函数;②函数中this指向apply的第一个参数;③apply接收两个实参,第二个参数是个数组,apply将第二个参数的数组按顺序拆散成多个实参传给函数。
function fun(params1, params2) { console.log(this.name) console.log(params1, params2) } var lilei = {name: 'LiLei'} var hanmei = {name: 'HanMei'} fun.call(lilei, 'lilei~', '20'); // LiLei lilei~ 20 fun.apply(hanmei, ['hanmei~', '18']); // HanMei hanmei~ 18
-
bind:①创建一个跟原函数一样的新函数,但不执行;②永久的替换新函数中的this指向;③bind可以接收其他实参做永久替换部分形参变量为固定的实参值
function fun(...arg) { console.log(this.name) console.log(...arg) } // bind返回的新函数可以多次调用 var zhangsan = {name: 'ZhangSan'} var zsfun = fun.bind(zhangsan) zsfun(1, 2, 3); // 输出结果:ZhangSan 1 2 3 zsfun('zs'); // 输出结果:ZhangSan zs // bind绑定永久参数 var zsfun2 = fun.bind(zhangsan, 100, 200) zsfun2(1, 2, 3); // 输出结果:ZhangSan 100 200 1 2 3 zsfun2('zs'); //输出结果:ZhangSan 100 200 zs
【注】
-
被bind()永久绑定的this,即便用call,也无法修改this的指向了,即多次bind绑定也只有第一次的生效
-
new操作的绑定操作优先度要高于bind,也会高于apply和call
总结:this指向
- 在全局作用域中,this指向window
- 在class中,this指向新创建的类实例
- 在函数中的this: