手写call apply bind 函数系列
手写call
Function.prototype.myCall = function(context, ...args) { // 解构context 与arguments if(typeof this !== 'function') { // this 必须是函数 throw new TypeError(`It's must be a function`) } if(!context) context = window; // 没有context,或者传递的是 null undefined,则重置为window const fn = Symbol(); // 指定唯一属性,防止 delete 删除错误 context[fn] = this; // 将 this 添加到 context的属性上 const result = context[fn](...args); // 直接调用context 的 fn delete context[fn]; // 删除掉context新增的symbol属性 return result; // 返回返回值 }
手写apply
和call类似,,只是apply的参数是数组
Function.prototype.myApply = function(context, args = []) { // 解构方式 if(typeof this !== 'function') { throw new TypeError(`It's must be a function`) } if(!context) context = window; const fn = Symbol(); context[fn] = this; const result = context[fn](...args); delete context[fn]; return result; }
call 和 apply的原理都是给那个对象加个属性,调用拿到返回值后再delete掉
手写bind
Function.prototype.myBind = function (context, ...args) { const fn = this; if(typeof fn !== 'function'){ throw new TypeError('It must be a function'); } if(!context) context = window; return function (...otherArgs) { return fn.apply(context, [...args, ...otherArgs]); }; };
bind 的原理是返回一个函数,这个函数最终使用的参数是创建和执行的参数的集合
拓展
关于 symbol的使用,可以参考这篇文章:理解 Es6 中的 Symbol 类型 ,每一种数据类型的出现都是为了解决特殊的问题,整理Symbol有以下应用场景:
- 使用Symbol来作为对象属性名(key)
- 使用 Symbol 定义类的私有属性/方法
- 模块化机制
- 使用Symbol来替代常量保证唯一性
- 注册和获取全局的Symbol
参考:https://zhuanlan.zhihu.com/p/158634772

浙公网安备 33010602011771号