call ,apply,bind 重写 ,带注释通俗易懂

废话不多说直接上代码 , 有错误与问题请指出
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)

努力把思想融入开发中,奥利给!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值