[英]JavaScript variable hoisting example
我有一个关于 JavaScript 中变量提升的问题。
考虑以下示例:
var myName = "Richard"; // Variable assignment (initialization)
function myName () {
console.log ("Rich");
}
console.log(typeof myName); // string
我实际上很困惑为什么typeof myName
作为string返回。
根据我的理解,该示例将按以下方式处理;
function myName ()
)将被提升到顶部,然后var myName = "Richard"
这一行(因为函数声明优先于变量声明)。 但是,由于已经存在名为“myName”的属性,因此该语句将被忽略。 因此typeof myName
应该作为函数(而不是字符串)返回。
我的理解哪里不对?
JavaScript 有一个动态类型系统,即变量的类型可以随时间改变。 基本上,您编写的内容是正确的:首先,函数声明会运行(在加载文件时),但随后存储在变量myName
的函数被字符串覆盖。
唯一被忽略的是对var
的调用,因为变量实际上已经声明了。
但是重新定义一个变量是完全有效的(这就是你在这里所做的,通过分配一个新值)。
最后,你的样本不过是这样的:
var x = 23;
x = 'foo';
这也将起作用, x
将是'foo'
,它的类型将是string
。 与您的示例的唯一区别是,在您的示例中,涉及function
类型的值。
除了其他答案之外,还应该注意的是,如果您以下列方式声明您的函数:
var myName = function() {
console.log('Rich');
}
或者干脆
myName = function(){
console.log('Rich')
}
与“function myName . . .”语法相反,typeof myName 将返回“function”
2 年过去了,但也许它仍然与某人有关 您是对的,在解释对象时确实如此:
扫描函数声明的上下文
扫描变量声明的上下文
但是,对于全局范围而言,情况似乎并非如此。 即,当我定义一个对象时,输出与它应该完全一样,当我在全局范围内定义相同时,它不是......仍然试图围绕这个
由于Hoisting
你的变量和函数定义被移到顶部,所以你有:
var myName;
// moved to top
function myName () {
console.log ("Rich");
}
// next your code
myName = "Richard";
console.log(typeof myName); // string
如果你像这样重写你的代码:
var myName = "Richard"; // Variable assignment (initialization)
myName = function () { // Variable redefinition
console.log ("Rich");
}
console.log(typeof myName); // function
你的myName
变量现在是一个函数,因为只有myName
变量被hoisted
:
var myName;
myName = "Richard"; // Variable assignment (initialization)
myName = function () { // Variable redefinition
console.log ("Rich");
}
console.log(typeof myName); // outputs 'function'
“提升”的想法是一种理解正在发生的事情的糟糕方式。 换句话说,在我看来,“吊装”是对吊装的不好解释。
真正发生的不是“提升”。 真正发生的是javascript分两个阶段执行代码:编译阶段和评估阶段。 javascript 社区称此为“提升”的症状,但大多数人无法理解为什么要提升提升,因为他们认为 javascript 解释器具有称为“提升”的此功能(他们没有)。
实际发生的事情比起吊的想法更容易解释。 规则是:
Javascript 总是自上而下地解析代码。 它从不重新排序代码(从不提升)。
执行有两个阶段:编译和评估。
所有声明都在编译阶段处理,在编译阶段不会评估任何表达式(因为“评估”事情是在评估阶段完成的)。
在求值阶段处理所有表达式和任何其他需要求值的内容。
记住规则 1,所有解析都是自上而下完成的,没有回溯,没有提升。
让我们以您的示例为例,并通过牢记 javascript 的编译和评估阶段来尝试理解它:
var myName = "Richard"; // Variable assignment (initialization)
function myName () {
console.log ("Rich");
}
console.log(typeof myName); // string
在编译阶段,解释器会看到你声明了一个变量。 它为此变量分配一块内存区域,并为其分配undefined
值。
在编译阶段,解释器会看到你声明了一个函数。 它还注意到函数名掩盖了变量名。 因此它创建了一个函数“myName”(这意味着此时变量myName
指向该函数)。
编译阶段结束。 现在我们进入评估阶段。
在评估阶段,解释器会看到您为myName
分配一个字符串。
当我们到达函数声明时,没有什么要评估的,因为声明是在编译阶段处理的。
在评估阶段,解释器会看到你 console.logging typeof myName
。 由于分配给它的最后一个东西是一个字符串,它打印“字符串”。
请注意,如果您删除字符串赋值,则myName
将是 typeof "function"。 那是因为在这种情况下,分配给它的最后一件事是声明的函数。
有关由两个执行阶段引起的其他微妙之处,请参阅此相关问题: JavaScript 函数声明和评估顺序
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.