废话不多说直接上代码 , 有错误与问题请指出
call实现
;(() => {
Function.prototype.myCall = function (ctx) {
ctx = ctx ? Object(ctx) : window
// 将 参数对象上面加一个对象 , 所以要保证ctx 是对象
ctx.pointer = this
// 声明一个空数组
const param = []
for (let i = 1; i < arguments.length; i++) {
param.push(`arguments[${i}]`)
}
// 接收一下范返回值
const ret = eval(`ctx.pointer(${param.toString()})`)
// 将上面新添加的属性删除
delete ctx.pointer
// 从新返回出去
return ret
}
// 测试
function test() {
console.log(this, arguments)
return 'value'
}
test.myCall({ a: 1, b: 2 }, '参数1', '参数2')
})()
apply实现
;(() => {
Function.prototype.myApply = function (ctx, args) {
ctx = ctx ? Object(ctx) : window
let ret
// 将 参数对象上面加一个对象 , 所以要保证ctx 是对象
ctx.pointer = this
// 判断 args 类型
const type = Object.prototype.toString.call(args).slice(8, -1)
if (type === 'Array') {
// 接收一下范返回值 , 利用 ... 展开表达式展开参数
ret = eval('ctx.pointer(...args)')
// 将上面新添加的属性删除
delete ctx.pointer
} else if (
type === 'Null' ||
type === 'Undefined' ||
type === 'Function'
) {
ret = eval('ctx.pointer()')
// 将上面新添加的属性删除
delete ctx.pointer
} else {
throw new TypeError('CreateListFromArrayLike called on non-object')
}
// 从新返回出去
return ret
}
// 测试
function test() {
console.log(this, arguments)
return 'value'
}
test.myApply({ a: 1, b: 2 }, function () {})
})()
bind 实现 : 这个有点不好理解 , 按照注释序号看就好了
// 特点 :
// 1 .返回一个新的函数
// 2. bind -> 第一个参数 -> 改变this指向
// 3. 接收参数分离
// 4.bind和 call的函数参数传递方式是一样的
// 5. 实例化返回的新函数 -> this.指向是 test 构造出来的实例
// 6. 实例应该继承 test 构造函数上的原型
Function.prototype.myBind = function (ctx) {
// 1.保存this
const pointer = this
// 2.第一次传递的参数
const params = [].slice.call(arguments, 1)
// 新建一个中间函数用于 赋值原型
const _typeFn = function () {}
// 返回新函数
const newFn = function (param) {
// 3.param 第二次传递的参数 利用 concat拼接
const args = params.concat(param)
// 4.调用函数 如果test有返回值就需要返回 5.判断this
return pointer.apply(this instanceof newFn ? this : ctx, args)
}
// 6.复制原型
_typeFn.prototype = pointer.prototype
newFn.prototype = new _typeFn()
return newFn
}
// 测试
function test(user, car) {
console.log(this)
console.log(user + '刚买了一辆' + car + '车')
}
test.prototype.fun = '方法'
const t = test.myBind({ a: 1, b: 2 }, '张三')
const t1 = new t('奔驰')
console.log(t1)
努力把思想融入开发中,奥利给!!!