先介绍var:知识点一:javascript函数var声明的内部机制:变量与函数不同; var的Hosting(提升特性);举例1 变量: alert(a); //undefined var a = 123;解析为: var a; //js在编译时会自动赋予undefined初值 alert(a); //undefined a = 123;过程: 先 初始化预编译 再 执行代码; 先查找出通过var定义的变量,初始化为:window.a=undefined。只是查找并不执行任何代码; 然后执行代码 alert (a)此时的a为window.a;举例2 函数:function(){ //var f1,function f2(){}; //hoisting,被隐式提升的声明 f1(); //ReferenceError: f1 is not defined f2(); // ok var f1 = function(){}; function f2(){}}
知识点二:javascript是没有块级作用域的。(与其他语言的不同);函数是JavaScript中唯一拥有自身作用域的结构。所以用let来弥补块级作用域;举例1:function foo(){ if(true){ var a ='qwe'; b='222'; //未进行声明 为 全局变量 } console.log(a); //'qwe'}; console.log(b); //'222'if 是没有作用域的;函数是JavaScript中唯一拥有自身作用域的结构;var的作用域为最近的函数,没有函数就是全局变量;举例2:(function(){ for(var i=0;i<3;i++){....}; console.log(i); //不报错, // i 并不会随着for循环的结束就销毁, // i会一直存在该函数中,也就是js没有块级作用域的概念 for (let i = 0;i<3; i++){... }; console.log(i); //报错 //let 声明的变量为块级作用域的变量})(); alert(i); //报错,不识别 //匿名函数中定义的所有变量都会在执行结束时被销毁
现在来看:var与let的不同var 最近的函数作用域 可重复定义let 声明的变量有块级作用域(兼容hosting 提升特性) 不可重复定义案例如下:var snack = 'Meow Mix';function getFood(food) { if (food) { var snack = 'Friskies'; //预编译时已经进行了局部变量snack的声明,没有块级作用域所以作用域 //为getFood函数 return snack; } return snack; //此时的sanck为局部变量snack};getFood(false); // undefined //snack预编译 但未 进行赋值所以为初始值undefinedlet snack = 'Meow Mix';function getFood(food) { if (food) { let snack = 'Friskies'; //作用域为if内部的snack 也是先声明后赋值 //重定义let变量会报错SyntaxError不如var容错性强 return snack; } return snack; //全局变量的snack }; getFood(false); // 'Meow Mix'
let局部变量可以解决的问题:(function() { var arr = [1, 2, 3]; for (let i = 0; i < arr.length; i++) { //循环变量每次迭代都会重新绑定 setTimeout(function() { console.log(arr[i]); // 1 2 3 }, 50); } })();若是var(function() { var arr = [1, 2, 3]; for (var i = 0; i < arr.length; i++) { //循环变量50秒以后访问i setTimeout(function() { console.log(arr[i]); // 3 3 3 }, 50); } })();