对fn 参数的赋值只是使该标识符指向匿名函数,外部范围内的foo 不受影响。
当您将对象作为参数传递时,可以说“引用是按值传递的”。该赋值只是替换了fn 标识符所指的位置。
这就是 evaluation strategy 在 JavaScript 中的工作原理。
就在fnChanger函数中的赋值之前,两个标识符,全局foo和fn参数,指向同一个函数对象:
---------------------------------------------
foo -----> |function foo { sys.print('未更改!'); } |
---------------------------------------------
^
|
fn -------------
赋值后,fn 将简单地指向新函数:
---------------------------------------------
富 -----> |函数 foo { sys.print('未更改!'); } |
---------------------------------------------
--------------------------------------
fn ------> |函数 { sys.print('已更改!'); } |
--------------------------------------
你怎么能改变它?
好吧,假设 foo 是全局范围内的函数,您可以这样做:
function fnChanger(obj, name) {
obj[name] = function() { sys.print('Changed!'); };
}
function foo() {
sys.print('Unchanged');
}
fnChanger(this, 'foo');
foo(); // Changed!
上面的方法会起作用,因为在fnChanger 函数中,我们需要一个基础对象和一个属性名称,在全局执行上下文中声明的函数被绑定为属性全局对象,因此我们可以用这种方式重新分配它的值。
fnChanger(this, 'foo'); 行也应该在全局范围内执行,它将传递 this 值(指的是此范围内的全局对象)和属性名称,允许您对 @ 进行赋值987654335@标识符。
如果该代码在函数内部,我们就无法获得基础对象,因为在这个“函数代码执行上下文”中,函数声明(变量声明和函数形式参数也是)被绑定为不可访问对象的属性,称为变量对象(这些变量对象的链,形成范围链),如果是这种情况,唯一的解决方法是使用eval.
更多信息: