相同之处:
都可以改变函数体内 this 的指向。
不同之处:
call、apply的区别:接受参数的方式不一样。
call接受的参数不是数组。
apply接受的参数是数组。
bind:不立即执行,返回的是一个函数。而apply、call 立即执行。
bind 除了返回是函数以外,它的参数和 call 一样。
默认实现使用
不带参数使用
var jack = {
name: "jack",
showName: function() {
console.log(this.name)
}
}
var tom = {
name: 'tom'
}
jack.showName(); //jack
jack.showName.call(tom); //tom
jack.showName.apply(tom); // tom
jack.showName.bind(tom)(); //tom
带参数使用
var jack = {
age: 1,
showAge: function(num1,num2) {
console.log(this.age + num1 + num2)
}
}
var tom = {
age: 12
}
jack.showAge(1,1); //3
jack.showAge.call(tom, 1, 1); //14
jack.showAge.apply(tom,[1, 1]); //14
jack.showAge.bind(tom, 1, 1)(); //14
模拟实现
call apply bind 底层是c++实现的,但是为了理解其内部实现,接下来我们用js简单模拟一下这三个函数的内部实现
js代码模拟实现call(myCall)
Function.prototype.myCall = function(thisArg, ...args) {
//保存需要被执行的函数
var fn = this
//简单边界判断
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window
//传入的对象thisArg,新增一个属性保存函数
thisArg.fn = fn
//通过新传入的对象调用函数,这一步导致需要被执行的函数this指向改变
var result = thisArg.fn(...args)
//删除属性
delete thisArg.fn
//返回结果
return result
}
//测试
var jack = {
age: 1,
showAge: function(num1,num2) {
console.log(this.age + num1 + num2)
}
}
var tom = {
age: 12
}
jack.showAge(1,1); //3
jack.showAge.myCall(tom, 1, 1); //14
js代码模拟实现apply(myApply)
Function.prototype.myApply = function(thisArg, argArray) {
var fn = this
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window
thisArg.fn = fn
var result
argArray = argArray || []
result = thisArg.fn(...argArray)
delete thisArg.fn
return result
}
//测试
var jack = {
age: 1,
showAge: function(num1,num2) {
console.log(this.age + num1 + num2)
}
}
var tom = {
age: 12
}
jack.showAge(1,1); //3
jack.showAge.myApply(tom, [1, 1]); //14
js代码模拟实现bind(myBind)
Function.prototype.myBind = function(thisArg, ...argArray) {
//获取到实际需要调用的函数
var fn = this
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window
function proxyFn(...args) {
//将函数放到thisArg中进行调用
thisArg.fn = fn
// 特殊: 对两个传入的参数进行合并
var finalArgs = [...argArray, ...args]
var result = thisArg.fn(...finalArgs)
delete thisArg.fn
//返回结果
return result
}
//返回函数
return proxyFn
}
//测试
var jack = {
age: 1,
showAge: function(num1,num2) {
return this.age + num1 + num2;
}
}
var tom = {
age: 12
}
console.log(jack.showAge(1,1)); //3
console.log(jack.showAge.myBind(tom, 1, 1)()); //14
console.log(jack.showAge.myBind(tom, 1)(1)); //14