Javascript 对象文字动态键
我在中学习了节点函数编程教程,但当我尝试实现第12课的代码时,如下所示Javascript 对象文字动态键,javascript,node.js,Javascript,Node.js,我在中学习了节点函数编程教程,但当我尝试实现第12课的代码时,如下所示 function Spy(target, method) { var store={}; var self=this; var copy=target[method]; store[target[method]]=0; console.log(store); console.log(store[target[method]]); target[method]=function(){
function Spy(target, method) {
var store={};
var self=this;
var copy=target[method];
store[target[method]]=0;
console.log(store);
console.log(store[target[method]]);
target[method]=function(){
store[target[method]]+=1;
return copy.apply(this,arguments);
};
return {count:store[target[method]]};
}
var spy = Spy(console, 'error');
console.error('calling console.error');
console.error('calling console.error');
console.error('calling console.error');
console.log(spy.count);
我在Spy中得到了
console.log(store)
,返回一个包含函数的对象。另外,最终返回返回{count:store[target[method]]}代码>从Spy返回未定义。有人能解释一下这两个原因吗?谢谢因为设置后存储[target[method]]=0
您正在将target[method]
设置为等于一个函数,这会弄乱store[target[method]]
的值,使其未定义。看起来您将要在返回上使用复制
值:
return {count:store[copy]};
虽然在这种情况下,计数仍然是0
,但这并没有帮助。这是因为您直接在Spy
中返回对象{prop:value,…}
,因此无法在Spy
函数中真正修改它。尽管要绕过将对象定义为构造函数中的变量(var returnObj={count:store[copy]};
),请返回该变量:return returnObj
。现在您可以更新returnObj.count
内部[target[method]]
这是因为JavaScript中的对象是通过引用传递的
功能间谍(目标、方法){
var-store={};
var self=这个;
var copy=目标[方法];
存储[目标[方法]]=0;
var returnObj={count:store[copy]};
目标[方法]=函数(){
returnObj.count+=1;
返回copy.apply(这个,参数);
};
返回OBJ;
}
var spy=spy(控制台“错误”);
console.error('调用console.error');
console.error('调用console.error');
console.error('调用console.error');
console.log(spy.count)代码>我想用我在您的代码中添加的额外日志来解释这些内容
function Spy(target, method) {
var store={};
var self=this;
var copy=target[method]; // #0.1
store[target[method]]=0; // #0.2
console.log('Before :: store', store); // #1
console.log('Before :: target[method]', target[method]); // #2
target[method]=function(){
store[target[method]]+=1;
return copy.apply(this,arguments);
}; // #3
console.log('After :: store', store); // #4
console.log('After :: target[method]', target[method]); // #5
return {count:store[target[method]]}; // #6
}
var spy = Spy(console, 'error');
console.log(spy.count);
target[method]
是一个类似于function(){[native code]}
(用js-lib编写的代码替换native代码)的函数
在0.2
中,您将此函数(以字符串形式)作为store
对象的键,并将其值分配给0
。
因此,您的存储对象看起来像
`Before :: store { 'function () { [native code] }': 0 }`
at#1
和目标[方法]
是位于#2
的本机函数
现在在#3
您正在为目标[方法]
分配一个新函数,因此现在目标[方法]
将引用您的新函数
因此,在#4
中,您的存储对象保持不变。(因为键是函数的字符串化值。)这是
`After :: store { 'function () { [native code] }': 0 }`
但是,由于您在#3
中进行了赋值,因此您的目标[方法]
值已更改为新函数,即
After :: target[method] function (){
store[target[method]]+=1;
return copy.apply(this,arguments);
}
现在在#6
您正试图从存储对象中获取一个密钥,而该存储对象在存储
对象中不存在,因此它返回未定义的
并将计数值存储到未定义的非常感谢,现在这完全有意义:)本机代码来自何处,它看起来不像是Spy的调用者传入的东西?本机代码来自javascript引擎。您的代码运行在实现ECMA规范的Js引擎之上。在这个实现中,它们是一个名为控制台
的对象,它具有错误
功能。此错误函数也有一些实现,在我们的日志中,本机代码中的指的是控制台.error()
的实现。非常感谢您的解释和解决方案:}只想添加一个后续,在我读过的是这样的真理,在JS中传递对象应该比C++中的指针传递更像是通过C++中的引用,因为指针可以被重写?@ Sehanh,我仍然认为它是通过引用的,因为这是它的功能如何工作,而只是稍微不同地实现。它过去了。基本上,它是按引用的值传递的,所以它是按值传递实现的,但功能的作用就好像它是按引用传递一样。非常感谢您的投入,非常感谢您的帮助:)