JavaScript: 在函数中初始化全局变量

JavaScript: initialize global variable in function

我有一个问题,对于您有经验的 JavaScript 程序员(我更像是一个 backend/DB 开发人员)来说,这个问题可能很明显。所以,如果这太简单了,请多多包涵!

我有这个代码:

var skill = "JavaScript";

function printSkill() {
    console.log(skill); // <-- This prints undefined
    var skill = "Java"; // <-- How can this possibly work?
    console.log(skill); // <-- This prints "Java"
}

printSkill();

输出为:

undefined
Java

我明白 运行 这段代码是可能的,因为 JavaScript 不是 编译的 ,它是在 运行 时间内解释的(这不会在例如 C++ 中编译)。但到底为什么这段代码有效呢?例如。为什么记录 undefined 而不是 "JavaScript" ,这在涉及范围规则时是显而易见的选择,例如C++。而且,第二条日志怎么打印出来"Java",不也是undefined吗?

这是幕后发生的事情:

var skill = "JavaScript";

function printSkill() {
    var skill; // skill is undefined and scoped to printSkill,
               // it is no longer the same `skill` variable
    console.log(skill); // <-- This prints undefined
    skill = "Java"; // <-- How can this possibly work?
    console.log(skill); // <-- This prints "Java"
}

printSkill();

这叫做变量hoisting

不要使用 var 关键字来创建全局范围:

var skill = "JavaScript"; // global variable

function printSkill() {
    console.log(skill); // <-- This prints JavaScript
    skill = "Java"; // remove "var" to keep it global
    console.log(skill); // <-- This prints "Java"
}

printSkill();

问题在于声明它:

var skill = "Java";

在函数内部,您正在使此 skill 变量的得分局限于函数范围。因此在函数内部第一个 print 语句给你 undefined 因为那时局部变量是未定义的。

JavaScript 分两次解析。首先它找到所有函数和变量声明,然后执行代码。这意味着对于编译器,您的代码如下所示:

// declaration
var skill = undefined; 

// declaration
function printSkill() {

    // declaration
    var skill = undefined;

    // execution
    console.log(skill);
    skill = "Java";
    console.log(skill);
}

// execution
skill = "JavaScript";
printSkill();

这种现象被许多人称为"hoisting",但他们完全不是"lifted up"。这就是编译器如何运行您的代码。

解决您的问题:

  • 如果您打算将范围内的 skill 替换为 Java,则在对其进行任何操作之前将声明和定义移至顶部。

  • 如果您打算替换全局 skill,则删除函数内 skill 上的 var

此功能在 javascript 中称为 提升 当您的代码为 运行 时,您的代码将变为:

var skill; function printSkill() {
    var skill;
    console.log(skill); // <-- This prints undefined
    var skill = "Java"; // <-- How can this possibly work?
    console.log(skill); // <-- This prints "Java" }

var skill = "JavaScript";
printSkill();

叫做scoping and hoisting.在javascript中有两种范围,它们是全局范围和函数scope.Injavascript 函数创建自己的作用域。

所以你的代码等价于下面的代码:

var skill;  // hoisted at the top of global scope and undefined

skill = "JavaScript";  // value assigned to it

function printSkill() {

    var skill;   //--> Hoisted at the top of function's scope and it is undefined 

    console.log(skill); // <-- So this prints undefined

     skill = "Java"; // <-- here it is assigned a value "java"

    console.log(skill); // <-- This prints "Java"

}

printSkill();

现在进入printSkill()里面的第二个技能变量。它有自己的 scope.It 调用函数 scope.And 在这个函数中定义的所有变量都被提升到它的包装函数范围的顶部, 不在全局范围.

所以当你在 pritSkill() 中 console.log() variable skill 时,首先它会在函数 scope.If 中查找它在那里找不到它然后它会查找 up 在范围 chain.In 你的情况下它发现技能提升在函数的顶部但它没有分配任何 value.So first console.log() 打印未定义。

在第二个 console.log() 中,它找到分配给技能的 value.So 它打印分配给技能的值


在你的代码中,如果你想初始化你的全局 skill 变量,你不能声明任何其他与全局同名的变量 one.Declaration 由于提升为,订单不算数我已经提到 above.Here 是应该如何编写代码。

注意:在代码中到处声明全局变量被认为是错误的编码习惯

var skill = "JavaScript";

function printSkill() {
    console.log(skill); // <-- This prints "javascript"
    skill = "Java"; // <-- assign value "Java" to global "skill" variable
    console.log(skill); // <-- This prints "Java"
}

printSkill();