目录
一、this指向的分类
1、全局函数的调用
2、对象中函数的调用
3、setTimeout与setInterval中的this
4、事件绑定中的this
5、箭头函数中的this
6、构造函数中的this
二、改变this指向的三个方法
1、临时改变this,且立即执行
2、永久改变this,不会立即执行
三、call、apply和bind的使用场景
this的指向基本遵循一句话:谁调用这个函数,函数里的this就指向谁。
如果是调用全局函数,那么函数中的this指向的就是window对象。
function f1(){
console.log(this) // window
}
f1()
因为我们定义的全局函数或者是全局变量,都是挂载在window身上的,所以全局函数的调用就相当于:window.函数名()。
在调用一个对象中的函数时,由于是通过对象调用,所以函数中的this指向的是该对象。
var obj={
a:1,
b:function(){
console.log(this)
}
}
obj.b()//obj这个对象
setTimeout和setInterval中使用this指向的是window。因为函数是以回调函数的形式存在的,回调函数被window所调用。
setTimeout(function(){
console.log(this)//window对象
},1000)
setInterval(function(){
console.log(this) //windowd对象
},200)
事件绑定中的this指向,即该事件绑定在谁身上,this指向的就是哪个节点,继而可以通过this操作节点的样式、内容等。
如果在箭头函数中使用this,该this的指向是上一级非箭头函数的this指向,或者说是父级对象的this指向。
btn.onclick=function(){
inp.onfocus=()=>{
console.log(this) //当输入框获取到焦点时,this指向的是btn
}
}
不论是前辈们定义好的,还是自定义构造函数,其中的this指向的都是当前的实例化对象。
function CreateObj(){
this.a="1",
this.b:function(){
console.log(this) //指向的是当前的实例化对象
}
}
var c1=new CreateObj()
c1.b() //指向的是c1
var c2=new CreateObj()
c2.b() //指向的是c2
在JS中,有三个方法可以改变this的指向:call、apply和bind。
语法:
需要借用this的对象.call/apply/bind(借给别人this的对象,传参)
其中的call和apply都只是临时的借用某个对象的this,并且会自动的执行当前的函数。
function calc() {
return this.name + "你好";
}
var nn = { name: "张三" };
// 这句话的意思是:将nn对象的this临时借给calc函数
var res=calc.call(nn);
//var res=calc.apply(nn);
console.log(res) //"张三你好"
上述例子使用apply和call的结果都相同,那么它们之间的区别是什么?
call和apply在传参时有不同:
剩余的bind方法作用就是永久的将某个对象中的this改变为另一个对象的this,改变之后原本的函数不会立即执行,需要手动的调用。
使用bind改变this总共做了三件事:
1)、创建了—个和原函数功能完全一样的新函数;
2)、将新函数中的this永久绑定为你指定的对象;
3)、将新函数中的部分参数永久固定;
function f1(){
return this.a
}
var obj={
a:123
}
var newF1=f1.bind(obj) //将f1的this永久改变为obj的this
console.log(newF1()) //123
注意:bind绑定在新函数中的this,无法被call、apply再次被借走。
function f1(){
return this.a
}
var obj={
a:123
}
var newF1=f1.bind(obj) //将f1的this永久改变为obj的this
console.log(newF1()) //123
function f2(){
console.log(this)
}
f2.call(newF1) //此时打印的是f1的内容,而不是newF1的内容
1、比较出数组中的最大值和最小值:Math.max/min.apply(Math,arr)
2、得到Object最原始的toString: Object.prototype.toString.call/apply(arr);
3、将类数组对象转为普通数组: var新数组=Array.prototype.slice.call/apply(伪数组对象)