实现call()
// this为调用函数
// context是参数函数
Function.prototype.myCall = function(context) {
// 判断调用者是否为函数
if(typeof this !== 'function'){
throw new TypeError('error')
}
// 不传参的话默认是window
context = context || window
// 新增fn属性,将值设置为需要调用的函数
context.fn = this
// 将arguments转化为数组将call的传参提取出来
const args = Array.from(arguments).slice(1)
// 传参调用函数
const result = context.fn(...args)
// 删除函数
delete context.fn
// 返回执行结果
return result
}
// 测试
function print(age){
console.log(this.name + ' ' + age)
}
var obj = {
name:'kobe'
}
// 调用函数的call方法
print.myCall(obj,1,2,3)
实现apply
Function.prototype.myApply = function(context) {
// 判断调用者是否是函数
if(typeof this !== 'function'){
throw new TypeError('error')
}
// 不传参默认为window
context = context || window
// 新增fn属性,将值设为需要调用的函数
context.fn = this
// 返回执行结果
let result
// 判断是否有参数传入
if (arguments[1]) {
result = context.fn(...arguments[1])
}else{
result = context.fn()
}
// 删除函数
delete context.fn
// 返回执行结果
return result
}
// 测试
function print(age,age2,age3) {
console.log(this.name+ ' ' + age + ' ' +age2 + ' ' +age3)
}
var obj = {
name:'kobe'
}
print.myApply(obj,[1,2,3])
实现bind()
Function.prototype.myBind = function(context) {
// 判断调用者是否为函数
if(typeof this !== 'function'){
throw new TypeError('error')
}
context = context || window
// 截取传递的参数
const args = Array.from(arguments).slice(1)
// _this指向调用函数
context.fn = this
// 返回一个函数
return function Fn(){
return args.length>0 ? context.fn(...args) : context.fn();
}
}
// 测试
let a = {
name: 'I am a',
sayName: function(out){
console.log(this.name+(out ? out:""));
}
};
let b = {
name: 'I am b'
};
a.sayName.myBind(b,['我是额外参数','参数2'])()
以上三种方法也参考了不少文章,手动实现这三个方法也是面试中必然会问道的,这三种方法还算简答明了,易理解