由于很多小白对this指向情况概念很模糊,本文将围绕js中的this的五种情况展开分析。
- 事件绑定
- 普通函数执行
- 构造函数执行
- 箭头函数
call、apply、bind
1、情况一:事件绑定
this:给元素的某个事件行为绑定方法,事件触发,方法执行,此时方法中的
this一般都是当前元素本身
1.1 DOM0事件绑定
<button id="btn">点我</button>
<script>
btn.onclick=function anonymous(){
console.log(this); //<button id="btn">点我</button>
}
</script>
1.2 DOM2事件绑定
addEventListener不兼容IE 6/7/8
方法一: <button id="btn">点我</button>
<script>
btn.addEventListener('click',function anonymous(){
console.log(this); =>元素
},false)
方法二: // 兼容iE 6/7/8 DOM2事件绑定
btn.attachEvent('onclick',function anonymous(){
console.log(this);//this指向window
})
</script>
- 特殊情况:如下图
function fn(){
console.log(this);
}
btn.onclick=fn.bind(window)
fn.bind(window)首先会返回一个匿名函数(AM),把AM绑定给事件,点击触发执行AM,AM中的this是元素,但是会在AM中执行fn,fn中的this是预先指定的window
2、情况二:普通函数执行
'点'前面是谁this就是谁
普通函数执行,它里面的this是谁,取决于方法执行前面是否有"点"
有的话,“点”前面是谁this就是谁,没有this指向window(严格模式下是undefined)
<script>
function fn(){
console.log(this);
}
let obj={
name:'OBJ',
fn:fn
}
// fn(); //=>window
// obj.fn() //=>OBJ
console.log(obj.hasOwnProperty('name') ); //hasOwnProperty方法中this:obj ture
console.log(obj.__proto__.hasOwnProperty('name'));//hasOwnProperty方法中this:obj.proto(Object.prototype) false
console.log(Object.prototype.hasOwnProperty.call(obj,'name')); // 等价于 obj.hasOwnProperty('name') ture
</script>
-
hasOwnProperty用来检测某个属性名是否属于当前对象的私有属性 -
in是用来检测是否为其属性(不论私有还是共有)
console.log(obj.hasOwnProperty('name'));
console.log(obj.hasOwnProperty('toString'));
console.log('toString' in obj);
3、情况三:构造函数执行(new xxx)
函数中的this是当前类的实列
<script>
function Fn(){
console.log(this);
//this.xxx=xxx是给当前实列设置私有属性
}
let f= new Fn;
</script>
4、情况四:箭头函数
-
箭头函数中没有自身的
this,所用到的this都是其上下文的this -
箭头函数没有的东西很多:
- 1.没有
prototype(也就是没有构造器),所以不能被new执行 - 2.它没有
arguments实参集合(可以基于...args剩余运算符获取)
<script> let obj={ fn:()=>{ console.log(this); //this:window } } obj.fn(); </script>箭头函数里
this不一定是window话不多说,看下面的代码:
<script> let obj={ name:'OBJ', fn:function(){ // console.log(this); //=>obj return ()=>{ console.log(this); //=>obj } } } let ff=obj.fn() </script> - 1.没有
5、情况五:、call、apply、bind
this:基于call/apply/bind可以改变函数中this的指向(强行改变)
5.1call/apply
- 第一个参数就是
this指向,写谁就是谁(特殊:非严格模式下,传递null/undfined指向的是window)
func.call([context],10,20)
- 唯一区别:执行函数的参数方式有区别,
call是一个个传递,apply是把需要传递的参数放在数组中整体传递
func.apply([context],[10,20])
<script>
let obj={
fn(x,y){
console.log(this,x,y);
}
}
obj.fn.call('',10,20); //String 10 20
obj.fn.apply('',[10,20]); //String 10 20
</script>
5.2 bind
call/apply都是改变this的同时直接把函数执行了,而bind不是立即执行函数,属于预先改变this和传递一些内容
【this的第五种情况写在下一章】