Aus*_*yde 6 javascript closures function pass-by-reference
假设我有这两个功能:
function fnChanger(fn) {
fn = function() { sys.print('Changed!'); }
}
function foo() {
sys.print('Unchanged');
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我打电话foo(),我看到Unchanged,正如预期的那样.但是,如果我fnChanger先打电话,我仍然会看到Unchanged:
fnChanger(foo);
foo(); //Unchanged
Run Code Online (Sandbox Code Playgroud)
现在,我认为这是因为foo没有fnChanger通过引用传递,但我可能是错的.
为什么不fnChanger换foo印刷Changed!?
此外,如何fnChanger在foo没有太多凌乱的语法的情况下进行更改?
PS:我正在使用node.js来测试所有这些东西,所以这就是它的sys.print来源.
对fn参数的赋值只是使该标识符指向匿名函数,foo在外部作用域中不受影响.
当您将对象作为参数传递时,可以说"引用按值传递".赋值只是替换fn标识符引用的位置.
这就是评估策略在JavaScript中的工作方式.
就在fnChanger函数赋值之前,两个标识符global foo和fnargument指向同一个函数对象:
---------------------------------------------
foo -----> |function foo { sys.print('Un changed!'); } |
---------------------------------------------
^
|
fn -------------
赋值后,fn只需指向新函数:
---------------------------------------------
foo -----> | function foo { sys.print('Unchanged!'); } |
---------------------------------------------
---------------------------------------
fn ------> | function { sys.print('Changed!'); } |
---------------------------------------
你怎么能改变它?
好吧,假设这foo是全局范围内的一个函数,你可以这样做:
function fnChanger(obj, name) {
obj[name] = function() { sys.print('Changed!'); };
}
function foo() {
sys.print('Unchanged');
}
fnChanger(this, 'foo');
foo(); // Changed!
Run Code Online (Sandbox Code Playgroud)
上面的方法是有效的,因为在fnChanger函数中,我们需要一个基础对象和一个属性名称,在全局执行上下文中声明的函数被绑定为Global对象的属性,因此我们可以用这种方式重新赋值.
该行也fnChanger(this, 'foo');应在全局范围内执行,它将传递this值(引用此范围中的Global对象)和属性名称,允许您对GlobalObject.foo标识符进行赋值.
如果该代码在函数内部,则我们无法获得基础对象,因为在此"函数代码执行上下文"中,函数声明(变量声明和函数形式参数也)被绑定为不可访问对象的属性,称为变量对象(这些变量对象的链,形成范围链),如果是这种情况,唯一的解决方法是使用eval.
更多信息: