JavaScript函数重载/覆盖

3
我正在努力理解IT技术方面的内容,请您给我点时间。
function test() {
  return 'foo';
}

console.log(test());

test = function() {
  return 'bar';
}

console.log(test());

function test(a, b) {
  return 'baz';
}

console.log(test());
console.log(test(true));
console.log(test(1, 2));

上述代码输出结果如下:

baz
bar
bar
bar
bar

但由于JavaScript是单线程语言且不存在函数重载的概念,我本以为输出结果应该是:

foo
bar
bar
baz
baz

请问有人能解释一下这是为什么吗?

3个回答

2

没错。我认为正在发生的事情如下:

  1. 使用 function test(...) { ... } 声明的函数会被提升到当前作用域的顶部。所以你使用该语法定义的两个函数都被提升到了顶部,但第二个定义覆盖了第一个,因此结果是 'baz.'

  2. 函数表达式不会被提升,例如 test = function (...) {...}。因此,当您将标识符 test 重新分配给该函数表达式时,它成为剩余脚本的 test 的值。

正如已经指出的那样,您不能在JavaScript中重载变量或函数。您可以使用新值覆盖变量,这就是您在示例中所做的。令人困惑的是JavaScript提升的工作方式。

如果您想避免提升,请使用 let myFn = function (...) { ... }.

以下是我理解的逐行解释:

// `test` defined with func declaration, hoisted to top
function test() {
  return 'foo';
}

console.log(test);
console.log(test());

// `test` overwritten with function expression, hoisting has already occurred,
// `test` identifier will have this value for remainder of script
test = function() {
  return 'bar';
}

console.log(test);
console.log(test());

// `test` overwritten with new func declaration, hoisted to top, but after first declaration
function test(a, b) {
  return 'baz';
}

console.log(test);
console.log(test());
console.log(test(true));
console.log(test(1, 2));

2

步骤如下:

function test() {
  return 'foo';
}

这是一个函数声明。在运行时之前,当它被解释时,将声明一个test变量。请注意保留HTML标签。
test = function() {
  return 'bar';
}

这是一个函数表达式。当执行这行代码时,test变量将被覆盖。

function test(a, b) {
  return 'baz';
}

这是另一个函数声明。在运行时之前,test变量再次被覆盖。

这就是为什么你的第一个版本的test函数从未被调用的原因。因为第二个函数声明在运行时之前覆盖了它。

更多关于函数声明和函数表达式的信息。


0
JavaScript 函数不能有重载,它们只会被覆盖。为了达到相同的效果,您需要在方法内区分不同的重载。
function test(a, b) {
  if(b)
     return 'baz';
  return 'foo';
}

1
这并没有完全解释发生了什么。你愿意更新你的答案,逐行和逐步地给出吗?例如,函数被声明并提升;函数被声明并提升,覆盖;第二个函数被调用;声明的函数被函数表达式覆盖等。 - Fissure King

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接