我正在关注here中的节点功能编程教程,但当我尝试实施第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(){
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)
返回一个包含函数的对象。此外,Spy的最终返回return {count:store[target[method]]};
返回undefined。任何人都可以解释这两个背后的原因吗?谢谢
答案 0 :(得分:1)
因为在设置store[target[method]]=0;
之后您将target[method]
设置为等于某个函数,这会混淆store[target[method]]
的值并使其未定义。您似乎希望在copy
上使用return
值:
return {count:store[copy]};
虽然在这种情况下count
仍然是0
,但这没有帮助。这是因为您直接在Spy
{prop: value, ...}
中返回了一个对象,因此您无法在Spy
函数中对其进行真正的修改。虽然为了解决这个问题,将对象{count:store[copy]}
定义为构造函数(var returnObj = {count:store[copy]};
)中的变量,然后返回该变量:return returnObj
。现在,您可以更新returnObj.count
内的[target[method]]
。
这是有效的,因为JavaScript中的Object
是通过引用传递的。
function Spy(target, method) {
var store={};
var self=this;
var copy=target[method];
store[target[method]]=0;
var returnObj = {count:store[copy]};
target[method]=function(){
returnObj.count+=1;
return copy.apply(this,arguments);
};
return returnObj;
}
var spy = Spy(console, 'error');
console.error('calling console.error');
console.error('calling console.error');
console.error('calling console.error');
console.log(spy.count);
答案 1 :(得分:0)
我想用你在代码中添加的其他日志来解释这些内容
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中编写的代码替换本机代码)。
在0.2
,您正在使用此字符串形式的函数({1}}对象并将其值分配给store
。
因此,您的商店对象看起来像
0
`Before :: store { 'function () { [native code] }': 0 }`
和#1
是target[method]
的原生函数。
现在#2
您正在为#3
分配一个新功能,所以现在target[method]
将引用您的新功能。
因此,在target[method]
,您的商店对象保持不变。 (因为key是函数的字符串化值。)
#4
但是由于您在`After :: store { 'function () { [native code] }': 0 }`
中进行了分配,因此您的#3
值已更改为新功能
target[method]
现在在After :: target[method] function (){
store[target[method]]+=1;
return copy.apply(this,arguments);
}
,你试图从#6
对象中不存在的商店对象中获取一个键,这就是为什么它store
并将count的值存储到{ {1}}