var 是一个函数作用域 function a(){ if(true){ var str="aa"; } console.log(str); } a();//aa 只要在 a()这个函数体内,var 声明的str变量里的值都可以被取到 var aa="11"; var aa="22"; console.log(aa);//22 let 是一个块级作用域 必须要先声明再使用 function a(){ if(true){ let str="aa"; console.log(str); } console.log(str); } a(); 脱离了if块之后,let生命的str变量将无法被取到,第二个console.log会报错,str未被定义,第一个console.log打印出aa let aa="11"; let aa="22"; console.log(aa);//报错显示aa已经被定义 两者区别根本原因: let不会存在变量提升,而var存在 console.log(str); var str="aa"//undefined let str="aa";//报错 str没有被定义 for(var i=0;i<5;i++){ } console.log(i);//5 通过var 声明 i变量提升变为全局变量 for(let i=0;i<5;i++){//let只在括号内有用处 } console.log(i);//let不存在变量提升 所以会报错 i未被定义 js是浏览器边解析边执行,解析器会优化代码, 谷歌V8引擎扫描函数体时,会对var优先执行,导致变量提升 暂时性死区(没有被定义的时候就可能被用到) var str="aa"; if(true){ str="123"; let str;//str没有被let定义赋值 } var x=y,y=2; function a(){ console.log(x,y);//undefined 2 } let x=y,y=2; function a(){ console.log(x,y);//报错:y没有被定义 } a(); 函数内部重新声明参数 function fun(i){ //let i; 这种方法不可取 if(true){ let i="as"; } }; let str="111"; if(true){ let str="112"; console.log(str);//112 } console.log(str);//111 var str="qq"; function fun(){ console.log(str);//undefined if(false){ var str="ww"; } } //函数内部存在变量提升,其实代码就是: var str="qq"; function fun(){ var str;//对str 只声明没有定义 console.log(str);//undefined if(false){ var str="ww"; } } let str="112"; function fun(){ console.log(str);//undefined if(false){ let str="113"; } } 符合预期的 for 循环 for(var i=0;i<3;i++){ setTimeout(function(){ console.log(i);//3 },10) } for(let i=0;i<3;i++){ setTimeout(function(){ console.log(i);//0 1 2 },10) } 可以看到在 for 循环中使用 let 方式声明变量才是符合预期。 在 for 中每一次循环,let 都是重新声明变量,并且因为 JavaScript 引擎会记住上一次循环的值,初始化 i 时在上一轮的基础上计算。 可以看到在 for 循环中至少有两层作用域,看下面的例子更容易理解。 for (let i = 0; i != 3; i++) { let i = 'seven' ; console.log(i); } console.log( 'eight' ); // 依次打印 seven seven seven eight
const声明一个只读的常量,常量的值不能被改变 |
---|
const类似于let,let是未赋值不能被调用,const会直接报错 不能只声明不赋值,一旦声明变量,必须初始化,不能以后赋值操作 const str={}; str.name="xiaobai"; str.action=function(){ consoole.log(this.name); } str={}; str.action()//报错 const 声明的变量必须设置初始值,且不能重复赋值。 const c3 = 'c3' ; let l3 = 'l3' ; var v3 = 'v3' ; console.log(c3, l3, v3); // 输出 c3 l3 v3 c3 = 2; // Uncaught TypeError: Assignment to constant variable l3 = 2; v3 = 2; console.log(c3, l3, v3); // 输出 c3 2 2 const c32; // 报错 // Uncaught SyntaxError: Missing initializer in const declaration |
const 定义常量,该常量不能赋值,但该常量的属性可以赋值 不能赋值其实就是它的指向不允许被修改 const str={}; const ary=[]; str.name="223"; ary.push("3"); console.log(str);//{name: "223"} console.log(ary);//["3"] // 禁止给对象赋值,应该使用 Object.freeze const c233 = Object.freeze({}); const c234 = Object.freeze([]); c233.name = 'seven' ; // 普通模式下不报错
// 严格模式下报错
// Uncaught TypeError: Cannot add property name, object is not extensible
c234.push(27);
// 普通模式下就会报错
// Uncaught TypeError: Cannot add property 0, object is not extensible
console.log(c233, c234);
// Uncaught TypeError: Cannot add property name, object is not extensible 全局变量不再设置为顶层对象(window)的属性,有效避免全局变量污染 const c24 = 'c24' ; let l24 = 'l24' ; console.log(c24, l24); // 输出 c24 l24 console.log(window.c24, window.l24); // 输出 undefined undefined |