模拟call函数
在Function.prototype上挂载一个_call函数表示对call的模拟,具体逻辑看注释
Function.prototype._call = function(context) {
//1 判断context是否是object,如果是object有可能是object或者null,如果不是则赋值一个空对象
if (typeof context === 'object') {
context = context || window //如果是null就会赋值window
} else {
context = Object.create(null)
}
//2 在context下挂载一个函数,函数名字随机生成,防止同名
var fn = +new Date() + '' + Math.random()
context[fn] = this //此时把函数赋值给context[fn],context[fn]变成了函数
//4 如果还有其他参数传入也要考虑
var args = []
for (var i = 1, len = arguments.length; i<len; i++) {
args.push('arguments['+ i + ']')
}
// 5 执行context[fn]这个函数,只能用eval,因为_call入参参数不确定
var result = eval('context[fn]('+ args+ ')')// args是一个数组,当它和字符串相加时会自动调用toString()转化成字符串
delete context[fn] //用完后从context上删除这个函数
// 6 返回结果
return result
}
模拟apply函数
Function.prototype._apply = function(context, array) {
if (typeof conetx === 'object') {
context = context || window
} else {
context = Object.create(null)
}
var fn = +new Date() + Math.random()
context[fn] = this
var args = null
if (array) {
args = []
for (var i = 0, len = array.length; i < len; i++) {
args.push('array[' + i + ']')
}
}
var result = eval('context[fn]('+ args+ ')')
delete context[fn]
return result
}
模拟bind函数
实现了apply和call函数后,bind就比较简单了 在外面包层function
Function.prototype._bind = function(context) {
if (typeof context === 'object') {
context = context || window
} else {
context = Object.create(null)
}
var args = []
for (var i = 1, len = arguments.length; i < len; i++) {
args.push(argument[i])
}
var fn = +new Date() + Math.random()
context[fn] = this
return function () {
var result = eval('context[fn](' + args + ')')
delete context[fn]
return result
}
}