Javascript:用另一个函数重新分配一个函数

发布于 2024-09-29 10:06:38 字数 656 浏览 6 评论 0原文

假设我有这两个函数:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

少年亿悲伤 2024-10-06 10:06:38

fn 参数的赋值只是使该标识符指向匿名函数,外部作用域中的 foo 不受影响。

当您将对象作为参数传递时,可以说“引用是按值传递的”。该赋值仅替换 fn 标识符引用的位置。

这就是 评估策略在 JavaScript 中的工作原理。

,两个标识符(全局 foofn 参数)指向同一个函数对象:

                ---------------------------------------------
    foo ----->  |function foo { sys.print('Un changed!'); } |
                ---------------------------------------------
                   ^
                   |
    fn -------------

fnChanger 函数中赋值之前 赋值后,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!

上面的代码可以工作,因为在 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 global foo and the fn argument, point to the same function object:

                ---------------------------------------------
    foo ----->  |function foo { sys.print('Un changed!'); } |
                ---------------------------------------------
                   ^
                   |
    fn -------------

After the assignment, fn will simply point to the new function:

                ---------------------------------------------
    foo ----->  | function foo { sys.print('Unchanged!'); } |
                ---------------------------------------------

                ---------------------------------------
    fn ------>  | function { sys.print('Changed!'); } |
                ---------------------------------------

How could you change it?

Well, assuming that foo is a function in the global scope, you could do something like this:

function fnChanger(obj, name) {
    obj[name] = function() { sys.print('Changed!'); };
}

function foo() {
    sys.print('Unchanged');
}

fnChanger(this, 'foo');
foo(); // Changed!

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 the this value (which refers to the Global object in this scope) and a property name, allowing you to make an assignment to the GlobalObject.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:

北方的巷 2024-10-06 10:06:38

正如@CMS 指出的,由于范围的原因,您无法在函数内分配它。但是,您可以像这样重新分配它:

var fnChanger = function() {
  return function() {
      alert('changed!');
  }
}

var foo = function() {
  alert('Unchanged');
}

foo = fnChanger();
foo();

示例

As @CMS pointed out you cannot assign it within the function due to the scope. However you could reassign it like this:

var fnChanger = function() {
  return function() {
      alert('changed!');
  }
}

var foo = function() {
  alert('Unchanged');
}

foo = fnChanger();
foo();

example

日久见人心 2024-10-06 10:06:38

有一种优雅的方法可以解决它

function fnChanger(fn_holder) {
    fn_holder["fn"] = function() { console.log('Changed!'); }
}
function foo() {
    console.log('Unchanged');
}

const foo_holder = {fn: foo}
fnChanger(foo_holder);

foo_holder["fn"]();  // Changed!

简短的解释:

  1. 将更高级别的引用foo_holder传递给fnChange,就像散列(或数组)一样。
  2. 将哈希 foo_holder["fn"] 中的元素重新分配为新值。这将更改内部引用指向的位置,而不是创建新引用。
  3. 然后您就可以享受更新后的功能了。

There is an elegant way around it

function fnChanger(fn_holder) {
    fn_holder["fn"] = function() { console.log('Changed!'); }
}
function foo() {
    console.log('Unchanged');
}

const foo_holder = {fn: foo}
fnChanger(foo_holder);

foo_holder["fn"]();  // Changed!

Short explanation:

  1. Pass a higher level reference foo_holder to fnChange like a hash (or an array).
  2. Reassign your element in side the hash foo_holder["fn"] to a new value. This will change where the inner reference is pointing instead of creating a new reference.
  3. Then you're good to have fun with your updated function.
深居我梦 2024-10-06 10:06:38

在 Javascript 中,函数是第一类对象,可以将其视为另一个变量。但为了让函数返回其结果,必须首先调用它。

当您调用 fnChanger(foo) 时,fn 变量实际上被 foo() 覆盖。

但您没有得到结果,因为该函数从未被调用。尝试返回它并调用如下所示,您将得到所需的答案。

function fnChanger(fn) {
  fn = function() {
    console.log('Changed!');
  }
  return fn;
}

function foo() {
  console.log('Unchanged');
}

fnChanger(foo)();
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.

function fnChanger(fn) {
  fn = function() {
    console.log('Changed!');
  }
  return fn;
}

function foo() {
  console.log('Unchanged');
}

fnChanger(foo)();
foo();

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文