javascript 参数和范围

javascript parameters and scopes

对这个 Eloquent Javascript explanation 参数和范围有点困惑。

它指出在函数外部声明的变量是全局变量,在函数内部声明的变量是局部变量,在函数内部声明的没有前面 var 的变量本质上是引用一个类似命名的全局变量。美好的。这就说得通了。但是这段代码让我陷入了循环。

var x = "outside";

var f1 = function() {
  var x = "inside f1";
};
f1();
console.log(x);
// → outside

var f2 = function() {
  x = "inside f2";
};
f2();
console.log(x);
// → inside f2

在第一个函数中注销 x 的值 应该 导致 "inside f1" 因为该变量是在本地声明的。第二个函数(因为它包含一个没有声明 var 的变量,因此引用了在最顶部声明​​的全局变量) 应该 导致 "outside." 但是...在任何一种情况下都不会。

我明白了应该发生的事情的要点。但除非我读错了,否则它似乎与作者描述的相反。这不可能是错别字。

f1 中的 x 是一个新变量 只能在 f1 中访问,并且对第一个全局 x。为了清楚起见,您问题中的示例代码基本上可以像下面这样编写:

    var globalX = "outside";
    var f1 = function() {
      var localF1X = "inside f1";
    };
    f1();
    console.log(globalX); // → outside

    var f2 = function() {
      globalX = "inside f2";
    };
    f2();
    console.log(globalX); // → inside f2

在 JavaScript 中,变量的作用域在函数级别(如果您在函数外部声明变量,则为全局级别)。

您可以在此处阅读有关 JavaScript 变量和 "hoisting" 的更多信息:http://javascriptissexy.com/javascript-variable-scope-and-hoisting-explained/

因此:

var x = 'a';
function f1() {
    var x = 1;
    console.log(x);
}

f1(); //outputs 1
console.log(x); //outputs 'a'

function f2() {
    x = 'b';
}

console.log(x); //still outputs 'a'

f2();

console.log(x); //now outputs 'b'

在函数内部声明的变量只能从这些函数内部访问(或scoped)。如果是这样的话样本可能会更清楚:

function f1() {
  var x = "Inside f1"; 
}

console.log(x);

将导致

ReferenceError: x is not defined

但是,如果函数的变量声明时没有 var,那么函数就是 implicit global(要么是不好的做法,要么是遗漏了错误):

function f2() {
  y = "Inside f2"; 
}

console.log(y);

将按您预期的方式工作,同时还声明一个隐式全局变量。

值得一提的是"use strict";,其中运行ES5's Strict Mode. You generally want to declare this inside a function, which causes the function to be run in strict mode, and avoids the semantics of strict mode from breaking interoptability中的代码与其他代码。

function f3() {
  "use strict";
  z = "Inside f3"; 
}

console.log(z);

将导致

ReferenceError: z is not defined

因为严格模式不允许您声明隐式全局。


根据您的评论澄清,隐式全局变量将 "overwrite" 彼此。更明确地使用 JavaScript 术语:

  • x = 10 将在环境的全局对象 x 上声明一个 属性,window.x 用于浏览器环境,global.x 用于 Node/IO 环境。
  • x = 20 将重新定义上面讨论的 属性。

这里有一个小片段,您可以在任何环境中 运行 证明这一点。我绝不是说你应该使用隐式全局变量,而是提供另一个例子来说明你为什么不应该使用。

function functionThatNeedsGreaterThan50(value) {
  // Skip checking the parameter because we trust the 
  // other developers on the team to make sure they call
  // this right. 
}

function f4() {
  q = 42; 
}

function f5() {
  q = 62; 
}

f4();
f5();

console.log(q);

// sometime thousands of calls later, one of which was
f4(); 

// I thought this was 62 but

functionThatNeedsGreaterThan50(q);