三者区别:
- call 和 apply 都是为了解决改变 this 的指向。作用都是相同的,只是传参的方式不同。
- 除了第一个参数外,call 可以接收一个参数列表,apply 只接受一个参数数组。
- bind不会立即调用,其他两个会立即调用。
// 使用
let developer = {
parent: function (a,b){
console.log(a,b)
console.log(this.name)
}
}
let obj={
name:'张三'
}
developer.parent.call(obj,1,2) // 1 2 张三
developer.parent.apply(obj,[1,2]) //arguments[1] // 1 2 张三
developer.parent.bind(obj)(1,2) //arguments[1] // 1 2 张三
call的简易模拟实现(es6)
- 函数定义在哪里 :
call是可以被所有方法调用的,所以毫无疑问的定义在 Function的原型上!
- 函数接收参数 :
绑定函数被调用时只传入第二个参数及之后的参数。
例如:Parent.call(this,1,2,3)
- 如何显式绑定this ?
如果调用者是函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。
Function.prototype.myCall= function (context = window) {
// let cxt = context || window;
// context为调用的上下文,this此处为函数,将这个函数作为context的方法
context.fun = this;
// 获取实参:返回一个数组[]
let args = Array.from(arguments).slice(1);
// 以对象调用的形式调用fun,此时this指向context,也就是传入的需要绑定的this指向
let res = arguments.length > 1 ? context.fun(...args ) : context.fun();
//不删除该方法会对传入对象造成污染
delete context.fun;
return res;
}
/************************************************************************/
//使用:
let developer = {
parent: function (a,b){
console.log(a,b)
console.log(this.name)
}
}
let obj={
name:'张三'
}
developer.parent.myCall(obj,1,2) // 1 2 张三
apply的简易模拟实现(es6)
- 思路
apply实现的思路与call基本相同,我们只需要对参数进行不同处理即可
例如:Parent.apply(this,[1,2,3]);
Function.prototype.myApply = function (context = window) {
// context为调用的上下文,this此处为函数,将这个函数作为context的方法
context.fun = this;
// 以对象调用的形式调用fun,此时this指向context,也就是传入的需要绑定的this指向
let res= arguments[1] ? context.fun(...arguments[1]) : context.fun();
//不删除该方法会对传入对象造成污染
delete context.fun;
return res;
}
/************************************************************************/
//使用:
let developer = {
parent: function (a,b){
console.log(a,b)
console.log(this.name)
}
}
let obj={
name:'张三'
}
developer.parent.myApply (obj,[1,2]) // 1 2 张三
bind的简易模拟实现(es6)
- 函数定义在哪里 ?
bind是可以被所有方法调用的,所以毫无疑问的定义在 Function的原型上!
- 函数接收参数 ?
bind函数返回一个绑定函数,最终调用需要传入函数实参和绑定函数的实参!!
例如:Parent.bind(this)(1,2,3);
- 如何显式绑定this ?
如果调用者是函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。
Function.prototype.myBind = function(context) {
//对context进行深拷贝,防止污染
context = JSON.parse(JSON.stringify(context)) || window;
// context为调用的上下文,this此处为函数,将这个函数作为context的方法
context.fun = this;
//获取实参
let args = Array.from(arguments).slice(1);
//bind返回一个绑定的函数,等待调用
return function () {
//这里需要注意一点的是需要对bind函数的实参和返回的绑定函数的实参进行参数合并,调用时传入;
let allArgs= args.concat(Array.from(arguments));
// 以对象调用的形式调用fun,此时this指向context,也就是传入的需要绑定的this指向
return allArgs.length > 0 ? context.fun(...allArgs) : context.fun();
}
}
/************************************************************************/
//使用:
let developer = {
parent: function (a,b){
console.log(a,b)
console.log(this.name)
}
}
let obj={
name:'张三'
}
developer.parent.myBind(obj)(1,2) // 1 2 张三
原文参考: 面试官:你能手写实现call,apply,bind方法吗?
网友评论