gpt4 book ai didi

javascript - 对模块方法的内部引用与导出引用

转载 作者:行者123 更新时间:2023-12-02 23:14:13 25 4
gpt4 key购买 nike

我试图更好地理解内部模块方法的引用与导出相同方法时创建的引用之间的差异的方式和原因。

我什至不确定我的术语是否正确,搜索信息也没有发现任何有用的信息。

一个简化的示例...我有一个执行一些数学运算的简单模块:

export const doubleNumber = (num) => {
return num * 2
}

export const squareNumber = (num) => {
return num * num
}

export default {
double: (num) => doubleNumber(num),
square: (num) => squareNumber(num),
}

...我有一些单元测试来验证功能:

import * as numProvider from './number-provider'

describe('the default methods', () => {
it('should call the correct math method when its property method is called', () => {
const doubleSpy = jest.spyOn(numProvider, 'doubleNumber')

const result = numProvider.default.double(1)

expect(result).toBe(2)
expect(doubleSpy).toHaveBeenCalledTimes(1)
})
})

( example project with the above code )

现在,当我运行测试时,它失败了。据我了解,我正在监视的方法(导出的方法)永远不会被调用,因为 numProvider.default.double 正在引用内部方法。

我可以通过将导出的方法附加到默认导出对象来验证这一点(并修复测试),double: (num) =>exports.doubleNumber(num) 但当然网站因浏览器中未定义 exports 而中断。

所以我的问题(我认为?)是..

JavaScript(或其他进程?)正在做什么导致创建这两个单独的引用?

最佳答案

What is JavaScript (or some other process?) doing that causes the creation of these two separate references?

问题的关键在于导出是对象上的属性,其中包含对模块内函数的单独引用,而您只能监视通过对象上的导出属性进行的函数调用。您不会监视底层函数本身,因此不会监视直接对底层函数进行的调用。

事实上,当您所拥有的只是对底层核心函数的引用时,Javascript 语言并没有提供一种方法来监视它。通过您拥有的任何引用来调用核心函数。声明函数会创建一个符号,并为其指定对您声明的函数的引用。声明一个导出,在对象上创建一个属性,并为其分配另一个对同一基础函数的引用。

监视对象会 Hook 该对象中的函数引用(将其替换为监视函数),并且它只能监视通过该对象属性进行的调用,因为只有那些调用才会真正调用替换监视函数。

我将给您一个使用普通对象的示例,以便您可以看到正在发生的情况,而不会增加导出的干扰:

// simple version of spyOn
const spy = function(obj, methodName) {
let orig = obj[methodName];
obj[methodName] = function() {
console.log(`spyhit for obj.${methodName}()`);
}
}

// core function
const doubleNumber = function(num) {
return num * 2
}

// object that contains reference to core function
const myObj = {
double: doubleNumber
};

// lets spy on myObj.double
spy(myObj, "double");

myObj.double(1); // generates spyhit
doubleNumber(1); // does not generate spyhit

在这里您可以看到,只有通过您监视 myObj.double() 的实际属性进行的调用才真正被监视。没有监视实际的核心功能。

这是因为 myObj.double 是 spy 功能的全部内容。该属性包含对 doubleNumber 的引用,但不是实际的函数本身。这里的 spy() 方法(与 jest 所做的类似)只是将实际属性替换为监视函数,以便它可以在调用时进行记录。但是,它并没有能力取代实际的核心功能本身。

关于javascript - 对模块方法的内部引用与导出引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57224977/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com