';吊装';JavaScript变量
我不完全理解为什么在接近尾声时显示“已悬挂”';吊装';JavaScript变量,javascript,hoisting,Javascript,Hoisting,我不完全理解为什么在接近尾声时显示“已悬挂” var x = 'set'; var y = function () { // WHAT YOU DON'T SEE -> var x; // is effectively "hoisted" to this line! if (!x) { // You might expect the variable to be populated at this point...it is not
var x = 'set';
var y = function ()
{
// WHAT YOU DON'T SEE -> var x;
// is effectively "hoisted" to this line!
if (!x)
{
// You might expect the variable to be populated at this point...it is not
// though, so this block executes
var x = 'hoisted';
}
alert(x);
}
//... and this call causes an alert to display "hoisted"
y();
任何指针都将不胜感激。变量声明将提升到范围的顶部。因此,您的代码与此等效:
var x = 'set';
var y = function () {
var x;
if (!x) {
x = 'hoisted';
}
alert(x);
}
y();
当执行y
时,var x
会对外部范围x
进行阴影处理,因此y
函数x
的内部在第一行声明之后未定义
因为变量声明(以及一般的声明)是在执行任何代码之前处理的,所以在代码中的任何位置声明变量等同于在顶部声明变量。这也意味着变量可以在声明之前使用。这种行为称为“提升”,因为变量声明似乎被移动到函数或全局代码的顶部
因此,在您的例子中,JavaScript知道在函数中的某个地方定义了一个局部变量(不是在外部声明的变量)x
,但在执行到达赋值给x
的赋值语句之前,它不知道它的实际值。(在编译时处理声明,在执行时完成赋值)直到赋值完成,将使用默认值undefined
。因为,这个条件,
if (!x) {
满足,并执行赋值语句。这就是您在警报框中被提升的原因
假设您没有在函数中声明x
var x;
var y = function () {
if (!x) {
x = 'hoisted';
}
alert(x);
}
y();
alert(x);
这里,由于函数中的任何地方都没有声明x
,因此在运行时,JavaScript将在更高的范围内查找x
。在这种情况下,它会在函数外部找到它。因此,将使用x
。由于您将highed
分配给x
,内部的警报也会显示highed
,并且在退出该功能后,alert(x)
也会发出警报highed
非常详细地解释变量的不同范围。在您的特定情况下,您可以使用参考:
this.x;
访问函数外部的全局x变量。因为在函数内部您试图访问未定义的变量,所以使用this
关键字可以引用函数外部的变量
以及
if(!x)
这是真的,因为您正在测试:<代码>是false 和<代码> x<代码>,因为在函数范围内不存在“代码>未定义< /COD>”,而<代码>未定义被认为是JS中的一个错误值,有关详细信息。
在javascript console.log中,函数内部为未通过的参数提供未定义的输出,但函数外部为未定义的错误,因为在函数内部浏览器显式声明变量。例如
console.log(x)
给出VM1533:1未捕获引用错误:未定义x,而
function test(x) {
console.log(x)
}
test();
给出未定义的。
这是因为函数test()被浏览器重写为:
function test(x) {
var x;
console.log(x)
}
另一个例子:-
var x =5 ;
function test(x) {
console.log(x)
}
test();
当函数变为
function test(x) {
var x;
console.log(x)
}
下例中的警报将给出未定义的:-
var x =5;
function test() {
alert(x);
var x =10;
}
test();
上述功能将变为:-
function test() {
var x;
alert(x);
x =10;
}
函数中javascript变量的作用域是函数级作用域,而不是块级。例如
function varScope() {
for(var i = 0; i < 10; i++){
for(var j = 0; j < 5; j++){}
console.log("j is "+j)
}
console.log("i is "+i);
}
varScope();
该功能再次变为:-
function varScope() {
var i;
var j;
for(i = 0; i < 10; i++){
for(j = 0; j < 5; j++){}
console.log("j is "+j)
}
console.log("i is "+i);
}
函数varScope(){
var i;
var j;
对于(i=0;i<10;i++){
对于(j=0;j<5;j++){}
console.log(“j是”+j)
}
console.log(“i是”+i);
}
使用此关键字有助于引用已挂起的函数外部的变量。
就你而言
this.x
更新:
从ES2015开始,使用const和let关键字使变量不被提升
示例:函数中挂起的全局变量
var x = "global variable hoisted";
function check_hoisting(){
alert(x); //undefined because of js hoisting
var x = "local variable";
}
check_hoisting();
示例:由于let关键字而未提升变量
let x = "global variable not hoisted";
function check_hoisting(){
alert(x);
var x = "local variable";
}
check_hoisting();
JavaScript只支持声明,不支持初始化。作为一名新程序员,无论我在这个或类似问题中读到多少答案,我都无法找到解决这个问题的方法。因此,我正在为其他人分享我的解决方案,比如我从绝望的搜索中来到这里(加上所有寻找修复的相关问题都被锁定并链接到这个问题)。所以这里有一个问题的答案,像我这样的新手可以理解如何以及为什么要更改代码来避免这个问题,并让变量返回我们期望的值。我的问题是,在学习javascript时,我假设每次我想要修改一个变量时,我都必须以var
开头,比如:
var myVariable = 1;
...
var myVariable = myVariable + 3;
var myVariable = 1;
...
myVariable = myVariable + 3;
实际上,您应该只在第一次(声明/初始化变量时)放入var
。在此之后的所有其他时间,您必须以变量名开始行,并删除var
,如:
var myVariable = 1;
...
var myVariable = myVariable + 3;
var myVariable = 1;
...
myVariable = myVariable + 3;
我一开始并没有发现我如何做的问题,直到我开始使用更多的函数,然后这些问题开始出现,我不明白为什么,我只是假设我不能在函数之间使用相同的变量名,或者我不能引用同一个函数之外的变量,或者,我不得不使用一些奇怪的方法,比如this.variable或window.variable,或者其他一些奇怪的方法,强制创建/使用全局变量
在我删除了所有我拥有的var
位置后,除了每个变量的第一个位置,我的问题消失了
这同样适用于您的代码。如果您更改此选项:
var x = 'set';
var y = function ()
{
if (!x)
{
var x = 'hoisted';
}
alert(x);
}
y();
(将变量x='highed';
更改为x='highed';
)更改为:
然后,它按照您的预期工作,并避免提升。它相当于var y=function(){var x;..
,这使得x
位于函数的本地,并且未分配。如果块不会“停止”var
从提升是,var x
提升到范围的顶部,这是JS中变量声明的正常行为。@Qantas94Heavy:这一个