课程名称:2周刷完100道前端优质面试真题
课程章节:第8章 前端面试技能拼图6: 编写高质量代码 - 正确,完整,清晰,鲁棒
主讲老师:双越
课程内容:
今天学习的内容包括:
8-14 手写函数bind功能
8-15 【连环问】手写函数call和apply功能
今天主要就是讲了 call apply bind 的写法。重点就是分辨清楚三种方法怎么用,外加如何实现绑定 this。
课程收获:
手写 bind
注意点:
- bind返回函数,
- 返回函数再次传参,需要参数拼接。
Function.prototype.cusBind = function (context, ...bindArg) {
// 当前函数
const self = this;
return function(...arg) {
const newArg = bindArg.concat(arg);
return self.apply(context, newArg)
}
}
function fn(a, b, c) {
console.info(this, a, b, c);
}
let bindFn = fn.cusBind({x: 100}, 10, 20);
bindFn(30) // {x: 100} 10 20 30
手写 call
注意点:
- 传入 this 为空 ( globalThis ) 和 非对象时处理 (new Object(context))。
- 函数绑定 this 时设置的,为了避免重复覆盖掉 this 原有属性,要用Symbol。且最后记得删除对应属性。
Function.prototype.cusCall = function (context, ...callArg) {
if (context == null) context = globalThis;
if (typeof context !== 'object') {
context = new Object(context);
}
// fn 通过作为属性绑定 this
const fnKey = Symbol();
context[fnKey] = this;
const res = context[fnKey](...callArg);
// this 删除 key
delete context[fnKey];
return res
}
function fn(a, b, c) {
console.info(this, a, b, c);
}
fn.cusCall({x: 100}, 10, 20, 30); // {x: 100, Symbol(): ƒ} 10 20 30
手写 apply
这个和 call 基本一模一样,只是入参有区别,第二个参数传参是数组。
Function.prototype.cusApply = function (context, applyArr) {
if (context == null) context = globalThis;
if (typeof context !== 'object') context = new Object(context);
// fn 通过作为属性绑定 this
const fnKey = Symbol();
context[fnKey] = this;
const res = context[fnKey](...applyArr);
// this 删除 key
delete context[fnKey];
return res
}
function fn(a, b, c) {
console.info(this, a, b, c);
}
fn.cusApply({x: 100}, [10, 20, 30]); // {x: 100, Symbol(): ƒ} 10 20 30
再写 bind
显然手写 bind 是没必要借助 apply 的。虽然老师没讲,自己写一下。
Function.prototype.cusBind1 = function (context, ...bindArg) {
if (context == null) context = globalThis;
if (typeof context !== 'object') context = new Object(context);
const fnKey = Symbol();
context[fnKey] = this;
return function(...arg) {
return context[fnKey]([...bindArg, ...arg]);
}
}
function fn(a, b, c) {
console.info(this, a, b, c);
}
let bindFn = fn.cusBind1({x: 100}, 10, 20);
bindFn(30) // {x: 100} 10 20 30
结束!