1.变量提升
- 使用 var 关键字声明的变量,无论其实际声明位置在何处,都会被视为声明于所在函数的
顶部(如果声明不在任意函数内,则视为在全局作用域的顶部)。这句话从字面上不难理解。
但是他是怎样一个过程,为什么会这样。当你代码中使用var 去声明一个变量或者函数时,
在浏览器引擎解析代码去执行之前会收集你var 变量放入内存中,根据作用域关联起来,此时
变量被声明出来。这就将当前作用域var变量提升到作用域顶部的过程。至于为什么会做变量提
升这件事需要理解浏览器引擎的工作原理这里不过多做介绍可以看一下这这个。
下边用一个例子来理解
function getValue(condition) {
console.log(value);// value 在此处可访问,值为 undefined
if (condition) {
var value = "blue";
// 其他代码
console.log(value);//此时 value 的值为 blue;
} else {
// value 在此处可访问,值为 undefined
console.log(value);
}
}
- 当执行getValue(false) 时,在value 未初始化值时去输出value 为undefined,在走else分支时同样也为undefined。
- 实际上当浏览器引擎解析以后去执行的代码是下面这样。同理当你用var声明一个函数时同样会被提升。
function getValue(condition) {
var value;//在解析时在作用域顶端先进行声明
console.log(value);
if (condition) {
value = "blue";
// 其他代码
console.log(value);
} else {
console.log(value);
}
}
2.块级声明
- 块级声明避免了变量提升,同事更加突显了作用域的划分,在一个函数内部或在一个代码块(由一对花括号包裹)内部
块级作用域内变量只在这一块作用域内生效。 -
let声明
let 声明的语法与 var 的语法一致。你基本上可以用 let 来代替 var 进行变量声明,但会将变量的作用
用域限制在当前代码块中(其他细微差别会在稍后讨论)。由于 let 声明并不会被提升到当前代码块的顶部,因此
因此你需要手动将 let 声明放置到顶部,以便让变量在整个代码块内部可用。这是书中对let的定义和解释,也就
是说你可以用let 代替 var 使用但是这涉及到你个人的编程习惯是否会受到影响,以及如何灵活应用 var 和 letfunction getValue(condition) { if (condition) { let value = "blue"; var value = "blue"; // 其他代码 console.log(value); } else { // value 在此处不可用 console.log(value);//condition=False 时候let 声明时直接报错value is not defined var声明时 undefine } console.log(value);//condition=True 时候let 声明时直接报错value is not defined var声明时 blue } 从上面例子可以看出来当使用let时 value 作用域被绑定在if的分支{}内在其他位置无法访问,程序会报错,使用var时由于变量提升 可以访问到value。由此也可以看出变量提升可能会造成一些问题但是它本身容错率更高,let的约束性更强。
const常量声明
const 声明的变量会被认为是常量(constant ),意味着它们的值在被设置完成后就不能再被改变。正因为如此,所有的 const
变量都需要在声明时进行初始化。const 声明的常量进行赋值会抛出错误。这个约束通常用于一些重要的且不会更改的变量定义,这
样如果不慎在代码中做出重新赋值的操作会抛出错误。增加了可调试性。但是有一点const强调的时禁止对变量的修改,但是如果是对象
那对象的属性成员修改不违反const约束。例子如下:
const person = {
name: "Nicholas"
};
person.name = "Greg"; // 工作正常
person = { // 抛出错误
name: "Greg"
};
- 全局块级绑定
当你用var声明一个全局变量时会被添加到window对象下,这样可能会覆盖原有可修改的属性,当你用let 声明一个全局变量时,不会被
添加到全局对象window上。例子:
console.log(window.name);//空字符串
var name='ok';
//let name='ok';
console.log(window.name);//'ok'
这里我采用的是window对象本身固有的一个属性name,初始为空字符串,当使用var声明name更改了name属性的值,当let声明
时对window下name属性无影响。
总结
文章都是以《深入理解ES6》读书笔记形式,大部分引用书中的定义,加上作者的理解,样例也做了调整,所有样例都可以放到console
里运行亲自尝试。
--by JK ES6学习笔记
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。