繁体   English   中英

在 javascript 中通过引用传递变量 - 在 mocha 中将变量传递给外部测试

[英]Passing variables by reference in javascript - passing variables to external test in mocha

我知道对于通过引用传递的原始数据类型在 javascript 中不起作用,因此解决方法是将它们包装在 object 中。 但是考虑一个场景,变量的初始 state 是null然后变量被重新分配为Object 现在,如果该变量作为参数传递给外部 function,它将作为引用传递还是最终在 function 内部undefined

作为参考考虑这个用例:

登录端点的摩卡测试中

方法一

describe('Login Endpoint Test', function(){
   let response = null;
   
   before('test pre-requisites', async function(){
      this.timeout(15000);
      response = await endpointCall(); //returns response Object
   });   

   it('simple endpoint test', function(){
      //response is availble here.
      response.should.have.status(200);
   });
  
   /*Importing an external testfile.*/
   require('./externalTest.spec.js')(response);
})

在 externalTest.spec.js

module.exports = (response) => {
   it('external test', function(){
     console.log(response);  // null;
   })
}
   

如果我将响应包装在Object中,它就可以工作。 为什么会这样?

方法二

如果我将响应包装在Object中,它就可以工作。 为什么会这样?

describe('Login Endpoint Test', function(){
   let data = {response: null};
   
   before('test pre-requisites', async function(){
      this.timeout(15000);
      data.response = await endpointCall(); //returns response Object
   });   

   it('simple endpoint test', function(){
      //response is availble here.
      data.response.should.have.status(200);
   });
  
   /*Importing an external testfile.*/
   require('./externalTest.spec.js')(data);
})

在 externalTest.spec.js

module.exports = (data) => {
   it('external test', function(){
     console.log(data.response);  // response object;
   })
}
   

注意:如果您发现不清楚,请告诉我。 提前致谢。

我能做的最直接的比较是 PHP,在这方面它与 Javascript 有一些相当大的差异。

首先,在 PHP 中,如果将数组传递给 function,并更改 function 中的数组,则原始数组实际上不会更改 如果您将数组传入,则该数组将按值完全复制

$arr = [];
func($arr);
var_dump($arr);

function func($arr) {
   $arr['key'] = 'value';
}

当您在 PHP 中使用var_dump($arr)时,您可能希望它具有'key' => 'value' ,但在 PHP 中并非如此。

javascript 中的相同示例如下所示:

 let obj = {}; func(obj); console.log(obj); function func(obj) { obj['key'] = 'value'; }

您可以看到,与 PHP 的数组示例不同,直接更改 Javascript 中的 object 会在两个地方都更改它。

这给我们带来了下一个重大区别 - PHP 具有完整的按引用传递功能,如下所示:

$arr = [];
func($arr);
var_dump($arr);

function func(&$arr) {
   $arr['key'] = 'value';
}

PHP 中的&符号表示按引用传递,因此在 PHP 的示例中,您会在var_dump($arr)时看到key => value

然而,这个&符号实际上并没有使 PHP 的这个变量的行为与 Javascripts 的行为相同。 因为在 PHP 中,它是一个 TRUE pass by reference,你可以这样做:

$arr = [];
func($arr);
var_dump($arr);

function func(&$arr) {
   $arr = 2;
}

因此,当您使用var_dump($arr)时,它将是 output 2 ,因为该func实际上在根本上改变了$arr的含义。

与 Javascript 相比, func function 无法更改obj的实际含义,它所能做的就是改变您发送的内容。 因此,如果您尝试在 javascript 中执行相同操作:

 let obj = {}; func(obj); console.log(obj); function func(obj) { obj = 2; }

...然后当你console.log(obj)你仍然会得到你开始使用的空 object 。 func无法通过使用=符号来改变外界认为obj所指的内容。

其实我想我对它是如何工作的有一些想法。

为什么方法 #1 失败了?

当需要并调用外部 function时,我们将响应变量传递给它。 此响应变量当前的值为null And before function reassigns response variable to a new response Object it is actually not updated in the execution context of the exported function , since null is one of the scalar primitive values (Number, String, Boolean, undefined, null, Symbol). 对于标量原始值 javascript 使用堆栈内存结构,并且在每次重新分配时,我们将在堆栈顶部添加一个新值并将变量指向它。 所以导出的 function 不知道推送到堆栈的新值,而只是对旧值的引用。

为什么方法#2成功

现在,当我们将响应包装为 object 时,我们有效地使用了两个 memory 结构,一个是堆栈,另一个是 响应的原始值存储在堆中,并在堆栈中维护对此的引用。 因此,当之前的 function 更新数据 Object 的键(响应)时,它实际上不会将新值送到堆栈顶部,而是在堆中更新,从而保持相同的引用。 因此,当it在导出的 function 中执行时,它可以找到原始数据。

希望这可以帮助。

我已经运行了你的代码,问题很简单。 我将用首先运行的行对其进行注释,以便您查看事件的顺序

1 describe('Login Endpoint Test', function(){ 
   2 let data = null;
   
   3 before('test pre-requisites', async function(){
      8 this.timeout(15000);
      9 data.response = await endpointCall(); //returns response Object
   });   

   4 it('simple endpoint test', function(){
      //response is availble here.
      10 data.response.should.have.status(200);
   });
  
   /*Importing an external testfile.*/
   5 require('./externalTest.spec.js')(data);
})

// different file
6 module.exports = (data) => {
   7 it('external test', function(){
     11 console.log(data.response);
   })
}

这里的重要位是(2)和(5)。 您是说data is null ,然后require expternalTest.spec.js and pass it whatever data is (which is null)

所以永恒测试.spec.js 只是立即获取数据为null ,它永远不会也永远不会有其他任何东西。 你已经通过了它null ,就是这样,就是这样。

在您的第二种方法中,执行顺序完全相同,但是您没有通过它 null,您已经通过了 object。 所以当然随着 object 的变化(并且response属性得到一个值), expternalTest.spec.js看到的data变化,因为data就是那个对象!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM