JavaScript 中的 call, apply, bind 这三个函数的做用和区别在各大论坛都被讨论了不少次了,可是我一直都还没来得及好好总结,此次正好看到了一个很不错的关于JavaScript 中 apply 、call 的详解,本身就学习并总结了一波~,正好更新一波博客😂javascript
其实 call 和 apply 的做用很明确,就是要经过对它们传入的参数来肯定函数上下文的对象,也就是经过参数来肯定函数中的 this 关键字的指向,this 关键字是 JavaScript 中一个很重要、很值得咱们去加深学习和理解的东西,具体关于 this 的知识总结,我之前写了一个博客,感兴趣的话请参考浅析JavaScript中的this关键字。java
call 和 apply 的做用是相同的,它们的惟一区别就是对传入参数的格式要求不一样。git
call()
github
call
方法在调用的时候,须要传入一个函数的上下文对象和一个参数列表数组
let obj = {
name: 'nicole'
}
let func = function (){
console.log(this.name)
console.log(arguments)
}
func.call(obj,{age: '20'},{id: '1'})
// 运行结果是打印出 nicole 和 [{age: "20"},{id: '1'}]
复制代码
函数的上下文被指向了传入的第一个参数obj,若是咱们直接调用func(obj,{age: '20'},{id: '1'})
,那么函数的 this 则指向了 window (严格模式下为 undefined)。app
apply()
函数
apply
方法在调用的时候,须要传入一个函数的上下文对象和一个数组学习
let obj = {
name: 'nicole'
}
let func = function (){
console.log(this.name)
console.log(arguments)
}
func.apply(obj,[{age: '20'},{id: '1'}])
// 运行结果是打印出 nicole 和 [{age: "20"},{id: '1'}]
复制代码
因为call
和apply
方法的做用都是同样的,因此在决定究竟要用哪一个的时候,咱们能够直接从参数的形式来考虑,若是咱们要传入的参数是数组,那咱们就直接使用apply
就好。ui
与call
和apply
方法不一样的是,call
和apply
方法在被调用时就直接执行了当前的函数,而bind
直接返回了一个改变了函数上下文以后的新函数,这个新函数与原函数并不是是同一个函数,并且与call
相似,bind
方法接受列表形式的参数this
let obj = {
name: 'nicole'
}
let func1 = function (){
console.log(this)
}
let func2 = func1.bind(obj,{age: '20'})
func1 === func2 // false
func2() // {name: "nicole"}
复制代码
咱们能够本身实现一个bind
函数
Function.prototype.bindTest = function () {
let self = this;
let context = Array.prototype.shift.call(arguments);
let arg = Array.prototype.slice.call(arguments);
return function () {
self.apply(context, [...arg, ...arguments]);
}
}
let obj = {
name: 'nicole'
}
let func1 = function () {
console.log(this);
console.log(arguments);
}
let func2 = func1.bindTest(obj)
func2({age: 11});
// 运行结果 {name: "nicole"} [{age: 11}]
复制代码
值得注意的是,bind
方法返回的函数里面的 this 值不能够再被改变了,也就是说不能再修改函数的上下文,无论再对函数调用call
仍是apply
,都没法再改变函数的上下文。而普通的函数则能借助call
仍是apply
各类肆意的修改函数的上下文。
let obj1 = {
name: 'nicole'
}
let obj2 = {
name: 'neil'
}
let func = function (){
console.log(this)
}
let func1 = func.bind(obj1)
func1.call(obj2)
// 运行结果是{name: "nicole"},也就是说虽然调用了func1的 call 方法,可是函数上下文依然是obj1
func.call(obj1) // {name: "nicole"}
func.call(obj2) // {name: "neil"}
func.apply(obj1) // {name: "nicole"}
func.apply(obj2) // {name: "neil"}
复制代码