JS中this的情况,apply,call和bind的理解
自己记录的笔记,仅作为自己的学习使用,如有错误请大家多多指出,谢谢大家。
1.this的情况
解析器在调用函数每次都会向函数内部传递一个隐含的参数 这个隐含的参数就是this,this指向的是一个对象 这个对象我们成为函数执行的上下文对象.关于执行上下文可以看之前我发的文章。
this的情况:根据函数的调用方式不同,this会指向不同的对象
- 当以函数的形式调用时,this是window
- 当以方法的形式调用时,谁调用方法this就是谁(方法是函数作为某个对象的属性时,称之为方法,this就是指的这个对象)
- 当以构造函数的形式调用时,this就是新创建的那个对象
2.apply call 和 bind
有时候我们需要修改this的指向,指向我们需要的地方。
apply call和bind的作用就是动态的修改当前函数内部环境对象this的指向。
也就是通过这三个函数,可以使用属于另一个对象的方法,改变了this指向,可以用另一个对象中声明的方法。
2.1. call
2.1.1使用方法
定义一个person对象:包含三个参数
var person = {
firstName:"Bill",
lastName: "Gates",
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
console.log(person.fullName()); //Bill Gates 此时this指向对象person
新创建一个对象person1
//新创建一个对象
const person1 = {
firstName : 'Steve',
lastName : 'Jobs'
}
//call 使用call函数 临时改变person中fullName函数的this指向 为对象person1
//此时对象person1就可以调用fullName方法
console.log(person.fullName.call(person1))//结果: Steve Jobs
同时也可以使用带参数的call方法
//同时也可以使用带参数的call方法
var person = {
fullName: function (city, country) {
//注意这里的参数city和country不需要加this 如果加this 输出则为undefined
//因为person1对象中 没有定义这两属性
return this.firstName + " " + this.lastName +" " + city + " " + country;
}
}
const person2 = {
firstName : 'Steve',
lastName : 'Jobs'
}
//同时也可以传入参数
console.log(person.fullName.call(person2, 'Liu', 'Xing'));//结果Steve Jobs Liu Xing
2.2 apply
2.2.1使用方法
apply()方法与call方法很类似,作用一样,使用方法也类似
不同之处就是:
接收参数的方式不同
call()方法的参数传递,是一个一个传递的,分别接收参数
但是apply()接收参数的方法是数组形式的参数。
如果要使用数组而不是参数列表,则使用apply()方法更方便。
继续使用上一个例子:
//在person1上调用person的方法
console.log(person.fullName.apply(person1, ['Liu', 'Xing']));//Steve Jobs Liu Xing
2.2.2应用场景
函数之间的相互调用。
例如使用Math.max()方法找到数组的最大数:
console.log(Math.max(1,2,3));//3
//js中数组没有max方法 所以可以使用apply方法 这样数组就调用了max方法
Math.max.apply(null,[1,2,3]) // 3 null的时候 this指向还是全局对象 也可以是" "
Math.max.apply(person1,[1,2,3]) //3
JavaScript 严格模式
在 JavaScript 严格模式下,如果 apply() 方法的第一个参数不是对象,则它将成为被调用函数的所有者(对象)。在“非严格”模式下,它成为全局对象。
2.3 bind
bind是永久修改函数this指向,但是它修改的不是原来的函数;而是返回一个修改过后新的函数,此函数的this永远被改变了,绑定了就修改不了。且传入参数的方式与call()方法一样,只能一个一个的传入。
2.3.1使用方法
let newFn = person.fullName.bind(person1,'Liu', 'Xing');//Steve Jobs Liu Xing
console.log(newFn())//此时newFn方法this指向就是person1
三者的区别
-
执行方式不同
call和apply是改变后页面加载之后就立即执行,是同步代码
bind是异步代码,改变之后不会立即执行,而是返回一个新的函数
-
传参方式不同
call和bind是一个一个传入,不能使用剩余参数的方式
apply可以使用数组的方式传入的,只要是数组方式就可以将剩余参数传入
例子: -
修改this的性质不同
call、apply只是临时的修改一次,也就是call和apply方法的那一次;当再次调用原函数的时候,它的指向还是原来的指向。
bind是永久修改函数this指向,但是它修改的不是原来的函数;而是返回一个修改过后新的函数,此函数的this永远被改变了,绑定了就修改不了。
3.参考文献
1.W3School讲解
2.Summer_dog的博客 讲解的很清楚,大家可以去看https://blog.csdn.net/qq_43000315/article/details/125360096