源码:
Function.prototype.selfCall = function(ctx, ...args) { ctx = ctx === null || ctx === undefined ? globalThis : Object(ctx); const fn = this; const key = Symbol(); Object.defeineProperty(ctx, key, { value: fn, enumberable: false, }); const r = ctx[key](...args); delete ctx[key]; return r; }
调用
function methods(a,b) { console.log('args', a, b); console.log('this', this); } methods.selfCall({ fn(){} })
解读:
这段代码定义了一个名为 selfCall 的方法,该方法被添加到了 Function.prototype 上,从而可以在任何函数对象上调用。这个方法模拟了 JavaScript 中的 Function.prototype.call 方法的功能,用于在指定的上下文(ctx)中调用函数,并且可以传递任意数量的参数。
让我们逐行进行详细解析:
1.Function.prototype.selfCall = function(ctx, ...args) {: 这行代码定义了一个名为 selfCall 的方法,该方法将被添加到 Function.prototype 上,这意味着任何函数对象都可以调用这个方法。该方法接受两个参数:ctx 表示要将函数调用应用到的上下文,args 是一个包含要传递给函数的参数的数组。
2.ctx = ctx === null || ctx === undefined ? globalThis : Object(ctx);: 这行代码检查传入的 ctx 参数是否为 null 或 undefined,如果是,则将 globalThis(全局对象,在浏览器中为 window 对象)赋给 ctx,否则将 ctx 转换为一个对象。这样做是为了确保函数调用的上下文不会是 null 或 undefined,因为在 JavaScript 中如果调用一个函数时上下文为 null 或 undefined,它会默认使用全局对象作为上下文。
3.const fn = this;: 这行代码将当前函数对象保存在 fn 变量中,以便后续可以在指定的上下文中调用它。
4.const key = Symbol();: 这行代码创建了一个新的唯一的 Symbol,用作临时属性的键,以确保在上下文对象中不会与现有属性冲突。
5.Object.defineProperty(ctx, key, { value: fn, enumberable: false, });: 这行代码使用 Object.defineProperty 方法将 fn 函数作为值,使用新创建的 Symbol 作为属性键,将其定义在 ctx 上。设置 enumberable 为 false,以确保这个属性不会出现在对象的枚举属性中。
6.const r = ctx[key](...args);: 这行代码调用了在上下文对象 ctx 上定义的函数,并传入了参数数组 args。这里利用了刚刚定义的临时属性键 key 来获取保存的原函数。
7.delete ctx[key];: 这行代码删除了之前定义的临时属性,在函数调用结束后,清理上下文对象中的临时属性,以防止污染。
8.return r;: 最后,将函数调用的返回值返回给调用者。
总的来说,这段代码实现了一个自定义的函数调用方法 selfCall,用于在指定的上下文中调用函数,并支持传递参数。在实现过程中,使用了 Symbol 作为临时属性的键,以确保在调用结束后能够正确清理上下文对象。