38个答案
范围界定规则
函数run(){ var foo=“foo”; 设bar=“bar”; console.log(foo,bar);// Foo酒吧 { var moo=“Mooo” 设baz=“Bazz”; console.log(moo,baz);// 穆奥巴兹 } console.log(moo);// 穆奥 控制台.log(baz);// 引用错误 } 运行();
var函数=[]; //让我们创建3个函数 对于(var i=0;i<3;i++){ //并将其存储在函数中 funcs[i]=函数(){ //每个都应该记录其值。 console.log(“我的值:”+i); }; } 对于(var j=0;j<3;j++){ //现在让我们逐一看看 函数[j](); }
吊装
功能检查提升(){ console.log(foo);// 未定义 var foo=“foo”; console.log(foo);// 富 } 检查吊装();
功能检查提升(){ console.log(foo);// 引用错误 让foo=“foo”; console.log(foo);// 富 } 检查提升();
创建全局对象属性
var foo=“foo”;// 全局范围的 让bar=“bar”;// 全局范围,但不是全局对象的一部分 console.log(window.foo);// 富 console.log(window.bar);// 未定义
重声明
'使用严格'; var foo=“foo1”; var foo=“foo2”;// 没问题,“foo1”被替换为“foo2”。 设bar=“bar1”; 设bar=“bar2”;// 语法错误:已声明标识符“bar”
-
76 -
259 -
302 -
75 让 块表达式 let(变量声明)语句 是非标准的,将来将被删除, bugzilla.mozilla.org/show_bug.cgi? 编号=1023609 . – 加尤斯 评论 2014年12月17日14:51 -
11 尽管let封闭块已弃用,但您也可以通过创建带大括号的显式块来完成相同的操作。 {让bar=foo;让foo=bar; 代码 ; 更多代码 ; console.log(bar+foo);} 只需将代码块顶部的let用大括号括起来。 – 埃里克·毕沙德 评论 2015年5月7日14:12
对于(var i=1;i<6;i++){ $(“#div”+i)点击(函数(){console.log(i);}); }
<script src=“ https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js “></script> <p>单击每个数字将登录到控制台:</p> <div id=“div1”>1 <div id=“div2”>2 <div id=“div3”>3 <div id=“div4”>4 <div id=“div5”>5
for(设i=1;i<6;i++){ $(“#div”+i)点击(函数(){console.log(i);}); }
<script src=“ https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js “></script> <p>单击每个数字将登录到控制台:</p> <div id=“div1”>1 <div id=“div2”>2 <div id=“div3”>3</div> <div id=“div4”>4 <div id=“div5”>5
-
80 这真的很酷。 我希望在括号内的循环体包含的外部定义“I”,而不是在“I”周围形成“闭包”。 当然,你的例子证明了另一种情况。 我认为从语法的角度来看,这有点令人困惑,但这种情况非常常见,因此以这种方式支持它是有意义的。 非常感谢您提出这个问题。 – 卡罗尔·科伦达 评论 2015年7月27日12:49 -
12 -
13 看起来你的回答是正确的行为: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – 吉姆·亨齐克 评论 2015年10月22日13:32 -
17 实际上,这是Javascript中的一个常见陷阱,现在我明白了为什么 让 会非常有用。 在循环中设置事件侦听器不再需要立即调用函数表达式来进行本地作用域 我 每次迭代时。 – 阿德里安·莫伊萨 评论 2016年2月21日8:12 -
26 使用“let”只是推迟了这个问题。 因此,每次迭代都会创建一个独立的私有块范围,但“i”变量仍然会被块内的后续更改损坏(假定迭代器变量不是 通常 在块内更改,但块内其他声明的let变量可能会更改),并且块内声明的任何函数在调用时都会损坏块内声明其他函数的“i”值,因为它们 做 共享相同的私有块范围,因此对“i”的引用相同。 – 加里 评论 2016年9月7日23:10
两者的区别是什么 让
和 无功功率,无功功率
?
//我在这里不认识 //这里不知道j //k在此已知,但未定义 //我在这里不认识 功能循环(arr){ //我在这里是已知的,但没有定义 //此处不知道j //k在这里是已知的,但只有一个值,称为第二个时间循环 //我在这里不认识 对于(var i=0;i<arr.length;i++){ //我在这里是已知的,并且有一个值 //此处不知道j //k在这里是已知的,但有一个值,只有第二个时间循环被调用 //我在这里不认识 }; //我在这里是已知的,并且有一个值 //此处不知道j //k在这里是已知的,但只有一个值,称为第二个时间循环 //我在这里不认识 for(设j=0;j<arr.length;j++){ //我在这里是已知的,并且有一个值 //j在这里是已知的,并且有一个值 //k在这里是已知的,但有一个值,只有第二个时间循环被调用 //我在这里不认识 }; //我在这里是已知的,并且有一个值 //此处不知道j //k在这里是已知的,但只有一个值,称为第二个时间循环 //我在这里不认识 } 回路([1,2,3,4]); 对于(var k=0;k<arr.length;k++){ //我在这里不认识 //此处不知道j //k在这里是已知的,并且有一个值 //我在这里不认识 }; for(设l=0;l<arr.length;l++){ //我在这里不认识 //此处不知道j //k在这里是已知的,并且有一个值 //l在这里是已知的,并且有一个值 }; 回路([1,2,3,4]); //我在这里不知名 //此处不知道j //k在这里是已知的,并且有一个值 //我在这里不认识
使用安全吗 让
今天?
如果您正在编写服务器端JavaScript代码( 节点.js ),您可以安全地使用 让 声明。 如果您正在编写客户端JavaScript代码并使用基于浏览器的transpiler(例如 练习者 或 babel-standalone公司 ),您可以安全地使用 让 语句,但您的代码在性能方面可能不是最佳的。 如果您正在编写客户端JavaScript代码并使用基于节点的transpiler(如 traceur shell脚本 或 巴别塔 ),您可以安全地使用 让 声明。 而且,由于您的浏览器只知道已传输的代码,因此性能缺陷应该受到限制。 如果您正在编写客户端JavaScript代码,并且不使用transpiler,则需要考虑浏览器支持。 仍有一些浏览器不支持 让 完全:
如何跟踪浏览器支持
-
23 关于答案v4: 我 在功能块中处处可见! 它开始于 未定义 (由于吊装),直到您指定一个值! 聚苯乙烯: 让 也被提升(至其承载块的顶部),但会产生 引用错误 当在第一次分配之前在块中被引用时。 (附言2:我是一个支持分号的人,但你真的不需要在块后加分号)。 话虽如此,感谢您添加有关支持的真实性检查! – 吉塔尔实验室 评论 2016年5月21日4:41 -
@GitaarLAB:根据 Mozilla开发者网络 :“在ECMAScript 2015中,let绑定不受Variable Hoisting的约束,这意味着let声明不会移动到当前执行上下文的顶部。”-总之,我对我的回答做了一些改进,这应该会澄清两个变量之间提升行为的差异 让 和 无功功率,无功功率 ! – 约翰·斯利格斯 评论 2018年2月26日23:37 -
2 你的答案进步了很多(我仔细检查了一下)。 请注意,您在评论中引用的同一链接也表示:“(let)变量位于 块的开头 直到处理完初始化。 “这意味着‘标识符’(文本字符串‘reserved’指向‘something’) 已经是了 保留在相关作用域中,否则它将成为root/host/window作用域的一部分。 就我个人而言,“吊装”只意味着将声明的“标识符”保留/链接到其相关范围; 排除其初始化/分配/可修改性! – 吉塔尔实验室 评论 2018年3月1日18:16 -
还有+ 1.你链接的凯尔·辛普森文章是 杰出的 阅读,谢谢你! “时间死区”也很清楚,即“TDZ”。 我想补充一件有趣的事:我在MDN上读到 让 和 常数 是 建议仅在您实际需要其附加功能时使用 ,因为强制/检查这些额外功能(如只写常量)会导致(当前)引擎执行/检查/验证/设置的“更多工作”(以及作用域树中的其他作用域节点)。 – 吉塔尔实验室 评论 2018年3月1日18:17 -
2 请注意,MDN表示IE确实正确地解释了let。 是哪一个? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – 卡廷卡·赫塞林克 评论 2019年2月6日12:42
让 工作原理非常类似
无功功率,无功功率 主要区别在于
无功功率,无功功率 变量是整个封闭函数
-
7 -
59 @奥利耶,实际上Mozilla正处于领先地位。 参见第19页,共页 ecma-international.org/publications/files/ecma-ST/ecma-262.pdf – 泰勒·克朗普顿 评论 2012年6月18日20:16 -
1 @泰勒·克朗普顿(Tyler Crompton),这只是多年来保留下来的一组单词。 当mozilla添加let时,它纯粹是一个mozila扩展,没有相关规范。ES6应该定义let语句的行为,但这是在mozila引入语法之后发生的。 记住moz也有E4X,它完全死了,只有moz。 – 奥利耶 评论 2012年7月11日18:49 -
11 IE11增加了对的支持 让 msdn.microsoft.com/en-us/library/ie/dn342892%28v=vs.85%29.aspx – 私奔 评论 2013年12月24日12:59 -
2
让
块范围
在顶层(函数外部)
var全局变量=42; 让blockScopedVariable=43; console.log(globalVariable);// 42 console.log(blockScopedVariable);// 43 console.log(this.globalVariable);// 42 console.log(this.blockScopedVariable);// 未定义
函数内部
(() => { var函数ScopedVariable=42; 让blockScopedVariable=43; console.log(functionScopedVariable);// 42 console.log(blockScopedVariable);// 43 })(); console.log(functionScopedVariable);// ReferenceError:未定义functionScopedVariable console.log(blockScopedVariable);// ReferenceError:未定义blockScopedVariable
在块内
{ var全局变量=42; 让blockScopedVariable=43; console.log(globalVariable);// 42 console.log(blockScopedVariable);// 43 } console.log(globalVariable);// 42 console.log(blockScopedVariable);// ReferenceError:未定义blockScopedVariable
在循环内部
对于(var i=0;i<3;i++){ var j=i*2; } 控制台.log(i);// 三 控制台.log(j);// 4 for(设k=0;k<3;k++){ 设l=k*2; } console.log(k类型);// 未定义 console.log(l类型);// 未定义 //尝试在此处执行console.log(k)或console.log(l)操作会引发ReferenceError。
带闭包的循环
//记录三次,不是我们的意思。 对于(var i=0;i<3;i++){ setTimeout(()=>console.log(i),0); } //按预期记录0、1和2。 for(设j=0;j<3;j++){ setTimeout(()=>console.log(j),0); }
时间死区
控制台.log(noTDZ);// 未定义 var noTDZ=43; console.log(hasTDZ);// ReferenceError:未定义hasTDZ 设hasTDZ=42;
无需重新申报
变量a; 变量a;// 效果很好。 让b; 让b;// 语法错误:已声明标识符“b” 变量c; 让c;// 语法错误:标识符“c”已声明
常数
无重新签名
常数a=42; a=43;// TypeError:赋值给常量变量。
常量对象={}; 对象a=42; 控制台.log(obj.a);// 42
const obj=Object.freeze({a:40}); 对象a=42; 控制台.log(obj.a);// 40 控制台.log(obj.b);// 未定义
需要初始值设定项
常数a;// 语法错误:常量声明中缺少初始值设定项
{ 设a=123; }; 控制台.log(a);// ReferenceError:未定义a
-
21 -
45 -
9 -
6
“使用严格”; console.log(“变量:”); 对于(var j=0;j<2;j++){ console.log(j); } 控制台日志(j); console.log(“let:”); for(设i=0;i<2;i++){ 控制台.log(i); } 控制台.log(i);
让 允许您声明在其上使用的块、语句或表达式的范围内受限的变量。 这与 无功功率,无功功率 关键字,它全局定义变量,或局部定义整个函数的变量,而不管块范围如何。
声明的变量 让 将定义它们的块以及任何包含的子块作为其范围。 这样, 让 工作原理非常类似 无功功率,无功功率 主要区别在于 无功功率,无功功率 变量是整个封闭函数:
函数varTest(){ 变量x=1; if(真){ var x=2;// 相同的变量! 控制台.log(x);// 2 } 控制台.log(x);// 2 } 函数letTest(){ 设x=1; if(真){ 设x=2;// 不同的变量 console.log(x);// 2 } 控制台.log(x);// 1 }`
在程序和功能的顶层, 让 ,不像 无功功率,无功功率 ,不在全局对象上创建属性。 例如:
var x=“全局”; 设y=“全局”; console.log(this.x);// “全球” console.log(this.y);// 未定义
当在块内使用时,let将变量的作用域限制在该块内。 请注意以下各项之间的差异 无功功率,无功功率 其范围在声明它的函数内。
变量a=1; var b=2; 如果(a===1){ 变量a=11;// 范围是全球性的 设b=22;// 作用域在if-block中 控制台.log(a);// 11 控制台.log(b);// 22 } 控制台.log(a);// 11 控制台.log(b);// 2
-
我不知道最后一个例子是否准确。 因为不是从函数调用它,而是从直接命令行调用它,它仍然被视为同一函数的一部分。 因此,如果从函数外部调用它,它的行为不应该相同。 评论 2020年8月28日18:20
-
14 -
8 -
4 意外地在事故中创建部分阻塞范围的想法是一个好主意,小心, 让 不提升,以使用由 让 定义在块的顶部。 如果您有 如果 语句,您可能忘记了在定义变量之前不能使用该变量。 很棒!!! – 埃里克·比沙德 评论 2015年5月7日14:01 -
1 这是let和var之间最重要的区别之一,这不在公认的答案中哈哈。 特别是考虑到由于吊装和范围界定可能出现的众多缺陷。 如果你不提到吊装,我觉得let和var之间没有太多区别。 – 杰伊 评论 2015年6月21日16:12 -
4 @EricB:是和否:“在ECMAScript 2015中, 让 将提升 变量设置为块的顶部。 但是,在变量声明之前引用块中的变量会导致 引用错误 (我的笔记:而不是老好人 未定义 ). 从块的开始到声明被处理,变量处于“暂时死区”。 “switch语句也是如此,因为只有一个底层块”。来源: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – 吉塔尔实验室 评论 2016年5月21日4:15
变量未提升 让 将 非起重机 它们出现在块的整个范围内。相比之下, 无功功率,无功功率 可按如下方式起吊。 { console.log(抄送);// 未定义。 吊装引起的 变异系数cc=23; } { 控制台.log(bb);// ReferenceError:bb未定义 设bb=23; } 实际上,佩尔·贝尔吉, 两者都有 无功功率,无功功率 和 让 已吊装 . 垃圾收集 块范围 让 与闭包和垃圾收集有关以回收内存非常有用。 考虑一下, 函数过程(数据){ //... } var hugeData={..}; 流程(hugeData); var btn=文档.getElementById(“mybutton”); btn.addEventListener(“点击”,功能点击(evt){ //.... }); 这个 点击 处理程序回调不需要 庞大的数据 完全可变。 理论上,之后 进程(…) 运行,巨大的数据结构 庞大的数据 可能会被垃圾收集。 然而,一些JS引擎可能仍然需要保持这种巨大的结构,因为 点击 函数在整个范围内有一个闭包。 然而,块范围可以使这个巨大的数据结构被垃圾收集。 功能过程(数据){ //... } {//此块内声明的任何内容都可以进行垃圾收集 让hugeData={..}; 流程(hugeData); } var btn=文档.getElementById(“mybutton”); btn.addEventListener(“点击”,功能点击(evt){ //.... }); 让 循环 让 循环中可以 重新绑定 对于循环的每个迭代,请确保重新为其分配上一次循环迭代结束时的值。 考虑一下, //打印5次 对于(var i=0;i<5;++i){ setTimeout(函数(){ 控制台.log(i); }, 1000); } 但是,请更换 无功功率,无功功率 具有 让 //打印1、2、3、4、5。 现在 for(设i=0;i<5;++i){ setTimeout(函数(){ 控制台.log(i); }, 1000); } 因为 让 创建一个新的词汇环境,其中包含a)initialiser表达式b)每个迭代(在前面计算增量表达式)的名称,更多详细信息如下 在这里 .
让 变量仅在其 最近的封闭 块( { ... } ). 让 变量只能在出现的代码行中使用 之后 声明变量(即使 它们被吊起了 !). 让 变量不能由后续 无功功率,无功功率 或 让 . 全球的 让 变量未添加到全局 窗口 对象。 让 变量是 易于使用 带闭包(它们不会导致 竟态条件 ).
示例
{ 设x=1; } console.log(`x是${x}`);// 解析期间ReferenceError:“x未定义”。
{ x=x+1;// 解析期间ReferenceError:“x未定义”。 设x; console.log(`x是${x}`);// 从不跑步。 }
设x=1; 设x=2;// 语法错误:已声明标识符“x”
var button=“我的名字太普通了,所以我会引发事故。”; let link=“虽然我的名字很常见,但我很难从其他JS文件访问。”; console.log(链接);// 好 啊 console.log(window.link);// 未定义(好!) console.log(window.button);// 好 啊
for(设i=0;i<5;i++){ console.log(`i是${i}`),125/*ms*/); }
i为0 我是1 我是2岁 我是3岁 我是4岁
for(设i=0;i<5;i++){ setTimeout(_=>console.log(`i是${i}`),125/*ms*/); }
对于(var i=0;i<5;i++){ setTimeout(_=>console.log(`i是${i}`),125/*ms*/); }
我5岁 我5岁 我5岁 我5岁 我5岁
-
11 #5不是由比赛条件引起的。 通过使用 无功功率,无功功率 而不是 让 ,代码相当于: var i=0; while(i<5){doSomethingLater();i++;} 我 不在关闭范围内,到那时 稍后做某事() 执行, 我 已经增加了5倍,因此输出为 我5岁 五次。 通过使用 让 ,变量 我 位于闭包中,因此每个异步调用都会获得其自己的副本 我 而不是使用使用创建的“全局” 无功功率,无功功率 . – 丹尼尔·T。 评论 2017年6月2日1:12 -
@丹尼尔: 我认为从循环初始值设定项中提升变量定义的转换并不能解释任何事情。 这只是语义的正常定义 对于 。虽然更复杂,但更精确的转换是经典的 for(var i=0;i<5;i++){(函数(j){setTimeout(_=>console.log( 我是${j} ),125/*毫秒*/);}) (i) ;} 它引入了一个“功能激活记录”来保存 我 名称为 j个 函数内部。 – 肉豆蔻 评论 2017年7月25日7:13
//一组加法器函数。 var加法器函数=[]; 对于(var i=0;i<1000;i++){ //我们希望索引i处的函数将索引添加到其参数中。 加法器函数[i]=函数(x){ //我在这里要做什么? 返回x+i; }; } var add12=加法器函数[12]; //哦哦。 该函数被绑定到外部作用域中的i,当前为1000。 console.log(添加12(8)===20);//=> 假 控制台.log(add12(8)===1008);//=> 真的 console.log(i);//=> 1000 //情况变得更糟了。 i=-8; 控制台.log(add12(8)===0);//=> 真的
//让我们再试一次。 //注意:我们正在使用另一个ES6关键字const来表示不需要的值 //被重新分配。 const和let具有类似的作用域行为。 常量加法器函数=[]; for(设i=0;i<1000;i++){ //注意:这次我们使用的是更新的箭头函数语法,但是 //使用上一示例中的“function(x){…”语法 //这里不会更改显示的行为。 加法器函数[i]=x=>x+i; } const add12=加法器函数[12]; //耶! 行为符合预期。 console.log(添加12(8)===20);//=> 真的 //我的范围没有扩展到for循环之外。 console.log(i);//=> ReferenceError:未定义i
const doubleAdderFunctions=[]; 对于(var i=0;i<1000;i++){ 常数j=i; 双加法器函数[i]=x=>x+i+j; } const add18=双加法器函数[9]; const add24=双加法器函数[12]; //调试这样的情况并不有趣,尤其是当 //代码比这个示例中的代码更复杂。 控制台.log(add18(24)===42);//=> 假 控制台.log(add24(18)===42);//=> 假 控制台.log(add18(24)===add24(18));//=> 假 console.log(添加18(24)===2018);//=> 假 控制台.log(add24(18)===2018);//=> 假 控制台.log(add18(24)===1033);//=> 真的 控制台.log(add24(18)===1030);//=> 真的
注: 这是一个教学示例,旨在演示
无功功率,无功功率 /
让 循环和函数闭包中的行为也很容易理解。 这将是一种可怕的数字相加方式。 但是,在其他环境中的现实世界中可能会遇到在匿名函数闭包中捕获数据的通用技术。 基督教青年会。
-
2 -
更正:技术上,此处描述的箭头函数语法=> developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – 巴顿 评论 2015年3月16日6:58 -
三
提升是一种JavaScript机制,其中包含变量和函数 声明被解析器移动到其作用域的顶部 在 实际的代码执行由JavaScript解释器开始。 所以,实际上 变量或函数在哪里声明并不重要,它们将 无论其范围是否为 全局或本地。 这意味着
控制台日志(hi); var hi=“说hi”;
实际上被解释为
var hi=未定义; 控制台日志(hi); hi=“打招呼”;
所以,正如我们刚才看到的,
无功功率,无功功率 变量正在被提升到顶部 它们的作用域,并且正在使用未定义的值进行初始化 这意味着我们可以在实际操作之前分配它们的值 在代码中这样声明:
hi=“打个招呼” console.log(hi);// 打个招呼 变量hi;
关于函数声明,我们可以在像这样声明它们之前调用它们:
sayHi();// 您好! 函数sayHi(){ console.log('Hi'); };
另一方面,函数表达式没有被提升,因此我们将得到以下错误:
sayHi()// 输出:“TypeError:sayHi不是函数 var sayHi=函数(){ console.log('Hi'); };
ES6引入了JavaScript开发人员
让 和
常数 关键字。 While期间
让 和
常数 是块范围的,不起作用 范围界定为
无功功率,无功功率 在讨论他们的 起重行为。 我们将从末尾开始,JavaScript提升
让 和
常数 .
console.log(hi);// 输出:初始化前无法访问“hi” 让hi=“hi”;
正如我们在上面看到的,
让 不允许我们使用未申报的 变量,因此解释器显式输出引用错误 表明
你好 之前无法访问变量 初始化。 如果我们更改以上内容,也会出现相同的错误
让 到
常数
console.log(hi);// 输出:初始化前无法访问“hi” const hi=“嗨”;
因此,最重要的是,JavaScript解析器搜索变量 声明和函数,并将它们提升到其范围的顶部 在代码执行之前,在内存中为它们赋值 如果解释器在执行代码时遇到他们 将识别它们,并能够使用它们执行代码 赋值。 用声明的变量
让 或
常数 保持 在变量执行开始时未初始化 用声明
无功功率,无功功率 正在使用值初始化
未定义 .
功能VS块范围:
函数testVar(){ if(真){ var foo='foo'; } console.log(foo); } testVar(); //日志“foo” 函数testLet(){ if(真){ 设bar=“bar”; } console.log(bar); } testLet(); //参考误差 //bar的作用域是if语句的块
让
变量无法提升:
console.log(letVar); 设letVar=10; //referenceError,变量未被提升
控制台.log(varVar); var变量=10; //日志未定义,变量被提升
全球的 让
无法连接到 窗口
:
var bar=5; 设foo=10; console.log(bar);// 日志5 console.log(foo);// 日志10 console.log(window.bar); //日志5,添加到窗口对象的变量 console.log(window.foo); //日志未定义,变量未添加到窗口对象
什么时候应该
让 被过度使用
无功功率,无功功率 ?
-
" 让 变量不会被提升: " 变量是用let还是const来声明的? - 让 声明 是被吊起的,而不是 初始化 这就是为什么 时间死区 存在-因为运行时可以在到达声明之前了解它。因此知道这是一个错误,因为在声明变量之前引用了它。 因为声明被取消了。 – VLAZ公司 评论 2023年9月18日12:15
-
11 吊装立柱不正确。 他们都提升变量。 与的区别 无功功率,无功功率 它们提升但不初始化为 未定义 值。 如果它们不提升,则不会在封闭块中屏蔽同名的变量: stackoverflow.com/q/63337235/2326961 – 盖里·奥加姆 评论 2020年8月11日9:43 -
(() => { var计数=0; for(设i=0;i<2;++i){ for(设i=0;i<2;++i){ for(设i=0;i<2;++i){ console.log(计数++); } } } })();
.as-console-wrapper{最大高度:100%!重要;}
(() => { var计数=0; 对于(var i=0;i<2;++i){ 对于(var i=0;i<2;++i){ 对于(var i=0;i<2;++i){ console.log(计数++); } } } })();
var x=1; var x=2;
设x=1; 设x=2;
var-->功能范围 let-->块范围 const-->块范围
函数x(){ var i=100; 控制台.log(i);// 100 } console.log(i);// 错误。 你不能这么做 x();
函数x(){ if(真){ var i=100; } 控制台.log(i); } x();
函数x(){ 函数y(){ var i=100; 控制台.log(i); } y(); } x();
函数x(){ 函数y(){ var i=100; } console.log(i);// 错误 } x();
if(真){ 设i=100; 控制台.log(i);// 输出:100 } 控制台.log(i);// 错误
函数x(){ if(真){ 设i=100; 控制台.log(i);// 输出:100 } 控制台.log(i);// 错误 } x();
console.log(x); var x=100;
控制台.log(x);// 错误 设x=100;
测试.js
{ 设l=“let”; const c=“const”; var v=“var”; v2='var 2'; } console.log(v,this.v); 控制台.log(v2,this.v2); 控制台.log(l);// ReferenceError:未定义l 控制台.log(c);// ReferenceError:c未定义
var SomeConstructor; { 让privateScope={}; SomeConstructor=函数SomeConstrator(){ this.someProperty=“foo”; privateScope.hiddenProperty=“bar”; } SomeConstructor.prototype.showPublic=函数(){ console.log(this.someProperty);// foo公司 } SomeConstructor.prototype.showPrivate=函数(){ console.log(privateScope.hiddenProperty);// 酒吧 } } var myInstance=新建SomeConstructor(); myInstance.showPublic(); myInstance.showPrivate(); console.log(privateScope.hiddenProperty);// 错误
函数a(){ {//这是let变量的最大范围 设x=12; } 控制台.log(x); } a();// 未捕获引用错误:未定义x
函数a(){//这是var变量的最大范围 { var x=12; } 控制台.log(x); } a();// 12
for(设i=0;i<10;i++){ 设置超时( 函数a(){ 控制台.log(i)// 打印0到9,这简直就是AWW!!! }, 100*i); }
对于(var i=0;i<10;i++){ 设置超时( 函数a(){ 控制台.log(i)// 打印10乘以10 }, 100*i); }
让统计数据=[16,170,10]; let[年龄、身高、年级]=统计; console.log(高度)
设x=120, y=12; [x,y]=[y,x]; 控制台.log(`x:${x}y:${y}`);
设节点={ type:“标识符”, 名称:“foo” }; 让{type,name,value}=节点; console.log(类型);// “标识符” console.log(名称);// “foo” console.log(值);// 未定义 设节点={ type:“标识符” }; 让{type:localType,name:localName=“bar”}=节点; console.log(localType);// “标识符” console.log(本地名称);// “酒吧”
吸气剂和setter 让
:
让jar={ Cookie数量:10, 获取厨师(){ 返回this.numberOfCookies; }, 设置cookie(值){ this.numberOfCookies=值; } }; console.log(jar.cookie) jar.cookies=7; console.log(jar.cookie)
-
请问这是什么意思 让{type,name,value}=节点; ? 您创建了一个具有3个属性type/name/value的新对象,并用node中的属性值初始化它们吗? – 阿兰伊布 评论 2017年6月15日7:55 -
1 -
-
1.、2.和3。 不依赖 让 。这是破坏性的。不是固有的 让 声明。 你可以使用 无功功率,无功功率 也。 此外,这根本不是“黑客”,而是官方语言规范的一部分。 jsbin.com/tibiquqohe/1/edit? js,控制台 基本上与“ 吸气剂和setter 让 : ”部分,但它显示了对象初始化语法。同样,与 让 . jsbin.com/qobelimamoda/1/edit? js,控制台 这个答案根本没有解决这个问题。 – VLAZ公司 评论 2023年9月18日12:04
设gfoo=123; if(真){ 设gfoo=456; } 控制台.log(gfoo);// 123 var hfoo=123; if(真){ var hfoo=456; } console.log(hfoo);// 456
let variableName=“a”; eval(“let”+variableName+'=10;'); 控制台.log(a);// 这不起作用
var variableName='a'; eval(“var”+variableName+'=10;'); 控制台.log(a);// 这个管用
-
2 你什么时候必须创建一个动态变量名,然后才能访问它? 创建对象并为其指定关键帧和值要好得多。 – 用户14029620 评论 2020年11月9日19:18 -
-
var cat=“cat”; let dog=“dog”; var动物=()=>{ var giraffe=“giraffe”; 让lion=“lion”; console.log(cat)// 将打印“cat”。 console.log(dog)// 将打印“dog”,因为dog是在此函数之外声明的(如varcat)。 console.log(长颈鹿)// 将打印“长颈鹿”。 console.log(lion)// 将打印“狮子”,因为狮子在范围内。 } console.log(长颈鹿)// 将打印“giraffe”,因为giraffes是一个全局变量(var)。 console.log(lion)// 将打印UNDEFINED,因为lion是一个“let”变量,现在已超出范围。
-
1 " var变量是全局变量,基本上可以在任何地方访问 " 这根本不是真的 无功功率,无功功率 声明要么是全局的,要么包含在函数中。 它们从来都不是唯一的全球性公司。 console.log(长颈鹿)// 将打印“长颈鹿”,因为长颈鹿是一个全局变量(var)。 这也是完全错误的,而且从来都不是这样。 – VLAZ公司 评论 2023年9月18日11:59 -
运行代码会给出:错误:{“message”:“ReferenceError:giraffe is not defined”,“filename”:“ stacksnippets.net/js “,”lineno“:26,”colno“:13} – 克里斯·希尔 评论 6月5日11:02 -
1
函数printnums() { //我在这里不方便 for(设i=0;i<10;i+=) { 控制台.log(i); } //我在这里不方便 //这里可以到达j 对于(var j=0;j<10;j++) { console.log(j); } //这里可以到达j }
区别在于范围界定。
无功功率,无功功率 范围最接近 功能 块 和
让 作用域为 最近的封闭块 ,其中 可以小于功能块。 如果在任何外部,两者都是全局的 块。 让我们看一个例子:
函数a(){ b; 让b; } a(); >Uncaught ReferenceError:b未定义
-
" 用var定义的变量将被附加到this对象。 “这是不正确的——它 只有 在全球范围内发生 只有 因为在全球范围内 这 与全局对象相同。 没有可连接的机制 无功功率,无功功率 声明 这 否则。 正好是两种不同机制的横截面。 jsbin.com/yujezitafo/1/edit? js,控制台 – VLAZ公司 评论 2023年9月18日11:45 -
" 如果在那里找不到[var声明],它将继续搜索Scope Chain。 let和const的情况并非如此。 “这也是不真实的-仍将检查范围链 让 或 常数 声明 jsbin.com/murobobiqe/1/edit? js,控制台 – VLAZ公司 评论 2023年9月18日11:47 -
" let和const的区别在于,const变量需要使用初始值设定项声明,否则会生成错误。 “这是一个反向解释。主要区别是 常数 不允许重新分配 .因此 因为 它不能重新分配,需要立即初始化。 否则,未初始化的声明将是一个错误,正如您所预料的那样,因为您以后无法赋值。 – VLAZ公司 评论 2023年9月18日11:51
(函数计时器(){ 对于(var i=0;i<=5;i++){ setTimeout(函数notime(){console.log(i);},i*1000); } })(); Stack VariableEnvironment//timer()的一个Variable环境; //当计时器超时时,每个迭代的值都是相同的 5.[设置超时,i][i=5] 4.[设置超时,i] 3.[设置超时,i] 2.[设置超时,i] 1.[设置超时,i] 0.[设置超时,i] #################### (函数计时器(){ for(设i=0;i<=5;i++){ setTimeout(函数notime(){console.log(i);},i*1000); } })(); Stack LexicalEnvironment-每个迭代都有一个新的词汇环境 5.[设置超时,i][i=5] 词汇环境 4.[设置超时,i][i=4] 词汇环境 3.[设置超时,i][i=3] 词汇环境 2.[设置超时,i][i=2] 词汇环境 1.[setTimeout,i][i=1] 词汇环境 0.[设置超时,i][i=0]
功能测试(){ 对于(var z=0;z<69;z++){ //托多 } //z在循环外可见 }
功能测试(){ for(设z=0;z<69;z++){ //待办事项 } //z未定义:( }