目录
1. call 的模拟实现
2. apply 的模拟实现
3. bind 的模拟实现
4. 三者异同
学习并参考于:
(一)call的模拟实现
call 用法 : MDN Function.prototype.call()
call()
方法使用一个指定的 this
值和可选的参数列表来调用一个函数。
call()
提供新的 this 值给当前调用的函数/方法。
1. call 实现主要思路:
-
将函数设为对象的属性
-
执行该函数
-
删除该函数
另外还有考虑:
- call 函数还能给定参数执行函数
- this 参数不传,或者传null,undefined, this指向window对象
- 函数是可以有返回值的
2. 实现:
Function.prototype.myCall = function () {
if (typeof this !== 'function') {
throw new TypeError('error!')
}
let context = arguments[0] || window //this 参数可以传 null,当为 null 的时候,视为指向 window
context.fn = this // 首先要获取调用call的函数,用this可以获取
let args = [...arguments].slice(1) //从 Arguments 对象中取值,取出第二个到最后一个参数
let result = context.fn(...args) //函数是可以有返回值的
delete context.fn
return result
}
3. 测试:
// 测试一下上面实现的myCall
var value = 2;
var obj = {
value: 1
}
function bar(name, age) {
console.log(this.value);
return {
value: this.value,
name: name,
age: age
}
}
bar.call(null); // 2
console.log(bar.myCall(obj, 'kevin', 18));
// 1
// Object {
// value: 1,
// name: 'kevin',
// age: 18
// }
(二)apply 的模拟实现
apply 用法:MDN Function.prototype.apply()
apply()
方法使用一个指定的 this
值和可选的参数数组 来调用一个函数。
apply 的实现跟 call 类似。
1. 实现:
Function.prototype.myApply = function () {
if (typeof this !== 'function') {
throw new TypeError('error!')
}
let context = arguments[0] || window
context.fn = this
let result = arguments[1] ? context.fn(...arguments[1]) : context.fn()
delete context.fn
return result
}
2. 测试:
var foo = {
value: 1
}
function bar(name, age) {
console.log(name)
console.log(age)
console.log(this.value);
}
bar.myApply(foo, ['black', '18']) // black 18 1
(三)bind 的模拟实现
bind 用法:MDN Function.prototype.bind()
bind()
方法会创建一个新函数,称为绑定函数。当这个新函数被调用时,bind()
的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。
bind是ES5新增的一个方法,不会执行对应的函数,而是返回对绑定函数的引用。
1. 实现:
Function.prototype.customBind = function () {
if (typeof this !== 'function') {
throw new TypeError('error!')
}
const that = this // 首先要获取调用bind的函数,用this获取并存放在that中
let context = arguments[0] || window
const args = [...arguments].slice(1)
return function() {
return that.apply(context, args.concat([...arguments]))
}
}
(四)三者异同
1. 相同:
- 改变函数体内 this 的指向
2. 不同:
- call、apply的区别:call方法接受的是参数列表,而apply方法接受的是一个参数数组。
- bind不立即执行。而call或apply会自动执行对应的函数。