bind,call,apply
- 共同点:
- 功能角度:三者都能改变
this 指向,且第一个传递的参数都是 this 指向的对象。
- 传参角度:三者都采用的后续传参的形式。
- 功能角度:三者都能改变
- 不同点:
- 传参方面: call 的传参是单个传递(序列),而 apply 后续传递的参 数是数组形式。而 bind 与call相同。
- 执行方面: call 和 apply 函数的执行是直接执行的,而 bind 函数会返回一个函数,然后我 们想要调用的时候才会执行。
call 模拟:
// this 为调用的函数 // context 是参数对象 Function.prototype._Call = function (context) { // 判断调用者是否为函数 if (typeof this !== 'function') { throw new TypeError('Error') } // 不传参默认为 window context = context || window // 新增 fn 属性,将值设置为需要调用的函数 context.fn = this // 将 arguments 转化为数组将 call 的传参提取出来 [...arguments] const args = Array.from(arguments).slice(1) // 传参调用函数 const result = context.fn(...args) // 删除函数 delete context.fn // 返回执行结果 return result; }
this为call的调用者 也就是 前者函数,也就是拿到调用者,将其赋给传入对象参数,对象参数调用,将this指向更改。
apply模拟
// 手写一个 apply 方法 Function.prototype._Apply = 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; }
bind函数
// 手写一个 bind 函数 Function.prototype._bind = function (context) { // 判断调用者是否为函数 if (typeof this !== 'function') { throw new TypeError('Error') } // 截取传递的参数 const args = Array.from(arguments).slice(1) // _this 指向调用的函数 const _this = this; // 返回一个函数 return function F() { // 因为返回了一个函数,我们可以 new F(),所以需要判断 // 对于 new 的情况来说,不会被任何方式改变 this if (this instanceof F) { return new _this(...args, ...arguments) } else { return _this.apply(context, args.concat(...arguments)) } } } // 普通函数 function test() { // new 的方式调用 bind 参数输出换做 [...arguments] console.log(this.name); }