JavaScript词法范围函数声明与定义

时间:2014-09-14 01:51:03

标签: javascript

如果函数在全局范围内声明,但在本地范围内定义,它属于哪个范围?我问,因为我知道它可以访问本地函数的范围(在其中定义),但声明让我感到困惑。

示例:

var funcDef;
function a() {
    var msg = "Hello, world!";
    funcDef = function() {
        return msg;
    }
}
a();
console.log(funcDef()); // prints Hello, world!

我的理解是变量,funcDef本身绑定到全局范围,其函数声明仍然绑定在()的范围内。有人可以证实吗?

3 个答案:

答案 0 :(得分:1)

忘记这是一个功能并将其视为变量的事实。假设您更改了函数a(请在下次选择更好的名称)将字符串值赋给funcDef。

console.log(funcDef);会在执行a()之前打印未定义,之后会打印字符串值。

这是类似的,funcDef的值在执行a()之前是未定义的,之后它会分配一个函数。

当然,以上是对实际情况的简化,但你可以这样思考。实际上,由于关闭,msg将在a()返回后保持不变并保持活动状态。

阅读本文以获取更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures

答案 1 :(得分:1)

function() { return msg; }只是funcDef的值,如5,true,依此类推,funcDef在全局范围内声明(因此在任何地方都可见)。

函数可以访问创建它们的执行范围(以及外部范围)。如果您再次调用a()funcDef的值将是一个不同的函数,可以访问不同的执行范围(因为它是在a的另一个调用中创建的)。

var funcDef;
function a(msg) {
    funcDef = function() {
        return msg;
    }
}

a("foo");
a("bar");
console.log(funcDef()); // bar

在创建它们的范围内可以看到函数。

var funcDef;

function a() {
  function f() { console.log(1); }
  funcDef = f;
}

a();

funcDef(); // works
f(); // fails, not visible
顺便说一句,经验法则:
- 如果声明的第一个令牌是关键字功能,则它是功能声明(因此它被提升到顶部) ;如果不是函数expresion ,它的行为就像一个普通的变量声明。

/* function declaration */

f(); // works

function f() { console.log(1); } 

/* function expression */

g(); // fails

var g = function () { console.log(2); };

/* function expression */

namedFunc(); // fails

var h = function namedFunc() { console.log(1); };

答案 2 :(得分:1)

这是一个非常好的问题。

正如@AlliterativeAlice所说,范围是直观的,预期的,全球化的。

现在funcDef知道msg的原因是其中最有趣的部分。

确实,正如@Ameen告诉你的那样,当你拨打a()时,你只是应用了一个闭包。

那时,funcDef“冻结”了对父范围和变量的引用。

因此,当您致电funcDef时,其范围msg的价值为Hello, world!