简介
为何会有此文呢?主要是网上大多手写 call
、apply
、bind
存在一定的问题。这里笔者修复了一些问题。【参考文章1 - 见文末】
为何这么说?主要是忽略了传入上下文对象中,直接写入 ctx.fn = this
诸如此代码,而用完后又直接进行了delete ctx.fn
,如此的粗暴。
此方法完全忽略了
ctx
中原先存在着fn
属性(固定属性值)的可能。此方法制作的新属性可能导致函数运行时对
ctx
进行属性遍历时导致逻辑错乱。
故此文主要解决这两个问题。
问题写法(以apply举例)
const util = require('../../util');Function.prototype.myApply = function (ctx, argArr) {
// 这里上下文为无效值时自动判定当前环境 // 浏览器中分配 window,node 中分配 global ctx = ctx || util.getGlobalHandle(); ctx.fn = this; let res = ctx.fn(...argArr ? argArr : []); delete ctx.fn; return res;}
此时,当测试样例如下时,与原生的结果截然不同。
describe('2020-11-21 making "myApply" incorrectly', function () {
let window = util.getGlobalHandle(); let obj = { numA: 123, fn: 333 }; function add(num1 = 11, num2 = 22) {
// console.log(`num1[${num1}], num2[${num2}]`, this); return this.numA + num1 + num2; } function add2(num1) {
return this.numA + this.fn + num1; } before(() => {
window.numA = 999; window.fn = 222; require('../../posts/2020-11-21/wrong_example'); }); after(() => {
delete window.numA; delete window.fn; delete Function.prototype.myApply; }); // 此时结果还是可以的 it(`"myApply" result should equal "apply" result`, () => {
assert(add.myApply(obj) === add.apply(obj)); assert(add.myApply(obj, [666]) === add.apply(obj, [666])); assert(add.myApply(obj, [666