Javascript:用另一个函数重新分配一个函数
假设我有这两个函数:
function fnChanger(fn) {
fn = function() { sys.print('Changed!'); }
}
function foo() {
sys.print('Unchanged');
}
现在,如果我调用 foo()
,我会看到 Unchanged
,如预期的那样。但是,如果我先调用 fnChanger
,我仍然会看到 Unchanged
:
fnChanger(foo);
foo(); //Unchanged
现在,我认为这是因为 foo
没有传递给 fnChanger
通过参考,但我可能是错的。
为什么 fnChanger
不更改 foo
来打印 Changed!
?
此外,如何让 fnChanger
更改 foo
而不需要太多混乱的语法?
PS:我使用node.js 来测试所有这些东西,所以这就是sys.print
的来源。
Let's say I have these two functions:
function fnChanger(fn) {
fn = function() { sys.print('Changed!'); }
}
function foo() {
sys.print('Unchanged');
}
Now, if I call foo()
, I see Unchanged
, as expected. However, if I call fnChanger
first, I still see Unchanged
:
fnChanger(foo);
foo(); //Unchanged
Now, I assume this is because foo
is not being passed to fnChanger
by reference, but I may be wrong.
Why does fnChanger
not change foo
to print Changed!
?
Furthermore, how can I get fnChanger
to change foo
without too much messy syntax?
PS: I'm using node.js to test all this stuff, so that's where the sys.print
comes from.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对
fn
参数的赋值只是使该标识符指向匿名函数,外部作用域中的foo
不受影响。当您将对象作为参数传递时,可以说“引用是按值传递的”。该赋值仅替换
fn
标识符引用的位置。这就是 评估策略在 JavaScript 中的工作原理。
,两个标识符(全局
foo
和fn
参数)指向同一个函数对象:在
fnChanger
函数中赋值之前 赋值后,fn
将简单地指向新函数:您如何更改它?
好吧,假设 foo 是全局范围内的函数,您可以执行以下操作:
上面的代码可以工作,因为在 fnChanger 函数中,我们需要一个 基对象和一个属性名称,在全局执行上下文中声明的函数被绑定为全局对象的属性,因此我们可以在那样。
fnChanger(this, 'foo');
行也应该在全局作用域中执行,它将传递this
值(引用此作用域中的全局对象) ) 和属性名称,允许您对 GlobalObject.foo 标识符进行赋值。如果该代码位于函数内部,我们就无法获取基对象,因为在这个“函数代码执行上下文”中,函数声明(变量声明和函数形式参数)被绑定为不可访问对象的属性,称为变量对象(这些变量对象的链,形成作用域链),如果是这种情况,唯一的解决方法是使用
评估。
更多信息:
The assignment to the
fn
argument just makes that identifier to point to the anonymous function,foo
in the outer scope is not affected.When you pass an object as an argument, one can say "references are passed by value". The assignment just replaces the location where the
fn
identifier refers to.That's how the evaluation strategy works in JavaScript.
Just before the assignment in the
fnChanger
functions, the two identifiers, the globalfoo
and thefn
argument, point to the same function object:After the assignment,
fn
will simply point to the new function:How could you change it?
Well, assuming that
foo
is a function in the global scope, you could do something like this:The above will work because in the
fnChanger
function, we require a base object and a property name, functions declared in the global execution context are bound as properties of the Global object, therefore we can re-assign its value in that way.The line
fnChanger(this, 'foo');
should be executed also in the Global scope, it will pass thethis
value (which refers to the Global object in this scope) and a property name, allowing you to make an assignment to theGlobalObject.foo
identifier.If that code were inside a function, there is no way we can get a base object, because in this "Function Code Execution Context", function declarations (variable declarations and function formal parameters also) are bound as properties of a non-accessible object, called the Variable Object (a chain of these Variable Objects, forms the Scope Chain), and if it were the case, the only workaround would be to use
eval
.More info:
正如@CMS 指出的,由于范围的原因,您无法在函数内分配它。但是,您可以像这样重新分配它:
示例
As @CMS pointed out you cannot assign it within the function due to the scope. However you could reassign it like this:
example
有一种优雅的方法可以解决它
简短的解释:
foo_holder
传递给fnChange
,就像散列(或数组)一样。foo_holder["fn"]
中的元素重新分配为新值。这将更改内部引用指向的位置,而不是创建新引用。There is an elegant way around it
Short explanation:
foo_holder
tofnChange
like a hash (or an array).foo_holder["fn"]
to a new value. This will change where the inner reference is pointing instead of creating a new reference.在 Javascript 中,函数是第一类对象,可以将其视为另一个变量。但为了让函数返回其结果,必须首先调用它。
当您调用 fnChanger(foo) 时,fn 变量实际上被 foo() 覆盖。
但您没有得到结果,因为该函数从未被调用。尝试返回它并调用如下所示,您将得到所需的答案。
In Javascript, functions are first class objects that can be treated just as another variable. But for the function to return its result, it has to be first invoked.
When you are invoking the fnChanger(foo), the fn variable actually gets overridden with foo().
But you are not getting the result because that function was never invoked. Try returning it and invoking as given below and you will the required answer.