[英]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.