细说 javascript 中变量声明 var、let、const 的区别
变量声明,每种编程语言必不可少的语法,在javascript中,变量的声明相对其他语言来说,算是比较简单的。
作用域(Scope)是什么
作用域是程序的执行环境,它包含在当前位置可访问的变量和函数。在 ES5 语法中,有全局作用域和局部作用域,ES6 则新增了块级作用域。
全局作用域是最外层的作用域,在函数外面定义的变量属于全局作用域,可以被任何其他子作用域访问。在浏览器中,window 对象就是全局作用域。在编写前端代码过程中,其中有一条优化规则就是少使用全局变量,因为全局变量容易导致程序BUG,并且不容易查找。
局部作用域的基本单元是 function
,只在函数体内有效。局部作用域是在函数内部的作用域。在局部作用域定义的变量只能在该作用域以及其子作用域被访问。
javascript中,变量声明使用 var
、const
、let
来声明变量,var
为ES5的语法,const
和let
为ES6之后的语法。ES6 的 let
和 const
为新引入的关键字,它们不会被提升,而且是块作用域。也就是说被大括号包围起来的区域声明的变量外部将不可访问。
下面我们就来说说各自的区别。
var 声明
var
声明,为ES5的语法,var
声明的变量总是归属于包含函数(即全局,如果在最顶层的话)。在 javaScript 函数内部声明的变量(使用 var
)是局部变量,所以只能在函数内部访问它(该变量的作用域是局部的)。可以在不同的函数中使用名称相同的局部变量,因为只有声明过该变量的函数才能识别出该变量。
提升(Hoisting)
在编译过程中,将var
和function
的定义移动到他们作用域最前面的行为叫做提升。
整个函数定义会被提升。所以,可以在函数还未定义之前调用它,而不用担心找不到该函数。
console.log(toSquare(3)); // 9function toSquare(n) { return n * n;}
变量只会被部分提升。而且只有变量的声明会被提升,赋值不会动。
开发者可能最希望实现 for
循环的块级作用域了,因为可以把随意声明的计数器变量限制在循环内部。
for (var i = 0; i < 10; i++) { console.log(i);}
立即执行函数能够有效解决:
for (var i = 0; i < 10; ++i) { (function (value) { console.log(value); })(i);}
再来看一个例子
(function () { var testValue = "hello"; var testFunc = function () { console.log("just test"); };})();console.log(window.testValue); // undefinedconsole.log(window.testFunc); // undefined
趣题:
var x = 10;var y = 20;[y, x] = [x, y];console.log(x, y); // 20 10
let 声明
过早访问 let
声明的引用导致的这个 referenceerror
叫做临时死亡区错误,在访问一个已经声明但还没有初始化的变量。创建一个块作用域。
let g1 = "global 1";let g2 = "global 2";{ g1 = "new global 1"; let g2 = "local global 2"; console.log(g1); // new global 1 console.log(g2); // local global 2 console.log(g3); // ReferenceError: g3 is not defined let g3 = "I am not hoisted";}
const 声明
const
是对赋值做锁定,不对值的改变锁定。例如:数组、对象。 一个常见的误解是:使用const
声明的变量,其值不可更改,但是对于数组和对象,其值是可以更改的。
const tryMe = "initial assignment";//下面重新赋值会导致程序错误tryMe = "this has been reassigned"; // TypeError: Assignment to constant variable.//对于数组是可以更改元素值const array = ["Ted", "is", "awesome!"];array[0] = "Barney";array[3] = "Suit up!";console.log(array); // [ 'Barney', 'is', 'awesome!', 'Suit up!' ]//下面这样更改整个数组,相对于重新赋值,是错误的array = ["Barney", "is", "awesome!", "Suit up!"];// 同样对于对象const airplane = {};airplane.wings = 2;airplane.passengers = 200;console.log(airplane); // { wings: 2, passengers: 200 }//下面是错误airplane = { wings: 2, passengers: 200 };
©著作权归作者所有:来自51CTO博客作者五月枫的原创作品,如需转载,请注明出处,否则将追究法律责任对于支持ES6的语法,建议默认使用
const
, 在确实需要改变的变量声明使用 let, 这样可以在某种程度上实现代码的不可变。从而可以避免很多的问题的出现。
更多相关文章
- Uboot启动参数说明
- 【粉丝问答19】为啥变量没初始化就用了?那是宏定义啊!
- 你的也是我的。局部变量透传(深入了解ThreadLocal)
- 变量的三个特征
- peerDependencies的具体作用
- 【DB笔试面试732】在Oracle中,Oracle Cluster Health Monitor(CHM)
- C语言之漫谈指针(上)
- Ansible 日常使用技巧 - 运维总结
- 【DB笔试面试672】在Oracle中,errorstack的作用是什么?