普通函数的this指向跟函数的调用有关
-
主动调用:
- 函数名() ===> this指向window
-
事件驱动调用:
- ele.on + 事件类型 = 函数名 ====>this指向ele元素
this是函数中的一个关键字,只有函数才有的一个关键字,谁调用这个函数,那么函数的thi就指向谁
<input type="button" id="btn" value="点击">
<script>
function fun(){
console.log(this);
}
fun() //直接调用,this指向window
btn.onclick = function () {
//给btn这个元素绑定点击事件,一点击就会执行fun函数,也就是相当于btn来执行fun函数,
//那么fun中this指向这个btn这个对象
console.log(this); //指向btn
}
再来看看另外一个小例子
var x = 10;
var obj = {
x:20,
say:function(){
console.log(this.x);
}
}
obj.say()//输出20
为什么这里会输出20,而不是10呢?因为obj调用了say方法的函数,所以this的指向是obj,所以在这里输出的值为20,正是应合了普通函数中的这句话:谁调用这个函数,那么函数的thi就指向谁
箭头函数中没有所谓的this指向(this本来就是一个关键字)
- 这个this跟箭头函数在哪里调用没有关系,但是跟箭头函数定义在哪里有关系
- 箭头函数中没有arguments这个关键字
来看这个例子
let obj = {
name:"aa",
say:()=>{
console.log(this);//定义所处的位置实在window这个位置的,所以这里的this指向window
}
}
console.log(obj.say());
然后我们在定义一个普通函数在obj对象里面
let obj = {
name:"aa",
say:()=>{
console.log(this);//定义所处的位置实在window这个位置的,所以这里的this指向window
},
go:function(){
console.log(this);//这个this指向obj.因为这个go方法是由obj来调用的,所以this指向obj
}
}
console.log(obj.say());
console.log(obj.go());
如果把say方法的箭头函数放到go方法函数里面去,看看会怎么样
let obj = {
name: "aa",
go: function () {
console.log(this);
let say = () => {
console.log(this);//此时这个say的this指向obj这个对象
}
say();
}
}
console.log(obj.go());
为什么这个say方法的箭头函数会指向obj,因为say在go方法的函数里面,此时的go是指向obj的,所以say会跟着指向obj
现在重新写一个函数
let fun = function () {
console.log(this)
}
fun()
顾名思义,这里的this指向是指向window,如果定义一个obj的对象,要将this的指向obj,这时候就要强行改变this的指向
- call() 直接执行函数
- 语法:函数名.call() 可以有多个参数
- 但是注意:第一个参数为this的指向,第二个以后的参数都是给原来的函数传递实参的
let obj = {
name:"张三"
}
let fun = function (info) {
console.log(this.name + info)//此时this指向obj这个对象,控制台打印 张三18
}
fun.call(obj,18)
- apply() 直接执行函数
- 语法:函数名.apply() 只有两个参数
- 但是注意:第一个参数为this的指向,第二个参数为一个数组(其实原来函数的实参)
let obj = {
name:"张三"
}
let fun = function (info) {
console.log(this.name + info)//此时this指向obj这个对象,控制台打印 张三今年18
}
fun.apply(obj,['今年18'])
如果要在apply()函数传递多个参数
let obj = {
name:"张三"
}
let fun = function (info) {
console.log(this.name + info)//此时this指向obj这个对象,控制台打印 张三今年18
}
fun.apply(obj,['今年18','好年轻呀'])
//此时控制还是打印 张三今年18
所以我们可以利用扩展运算符将对应传递的实参展开
let obj = {
name:"张三"
}
let fun = function (...info) {
console.log(this.name + info)//此时this指向obj这个对象
}
fun.apply(obj,['今年18','好年轻呀'])
//此时控制还是打印 张三今年18,好年轻呀
- bind() 不直接执行函数
- 语法:函数名.bind()
- 返回值:一个新函数(跟原函数一模一样,只不过新函数这个this指向改变了)
- bind的参数只有一个,这个参数为this的指向
- 原函数的实参给bind函数的返回值添加
let obj = {
name:"张三"
}
let fun = function (...info) {
console.log(this.name + info)//此时this指向obj这个对象
}
var res = fun.bind(obj)
res('aa')