let命令
let命令用于声明变量,但是只在代码块中有效,如下见与var的区别:
for (var i = 0; i < 10; i++) {
a[i] = function() {
console.log(i);
};
}
a[6](); //10
for (let i = 0; i < 10; i++) {
a[i] = function() {
console.log(i);
};
}
a[6](); //6
如上, var在全局范围内有效,所以console.log中i指向的i即为全局i,即为所有数组成员里的i,因此输出10;而let声明的i只在本循环内有效,每次的i都是一个新的变量,由于js引擎内部机制,会记住上一轮循环的值作为本轮i的初始化(莫名觉得想甩又甩不掉的样子),所以,最后会输出6。
此外,let不存在变量提升,var会输出undefined,let会报错;let 会存在暂时性死区,如以下代码所示;let不允许重复声明,会报错
function func(arg) {
let arg;
}
func() // 报错,同一作用域
function func(arg) {
{
let arg;
}
}
func() // 不报错,因为两个arg不在同一作用域
块级作用域
块级作用域与函数声明
这里有一点比较拗口,大概意思是这样,本来在ES6中块级作用域里声明一个函数,应该和let声明一样硬气的,我就只在块级作用域中厉害,外边不准用,但是在ES5环境中运行,会出现如下的的结果,ES6理论上来讲会打印“I am outside!”,但实际上却会报错,因为如果改变了块级作用域内声明的函数的处理规则,会对老代码产生很大影响,所以为了兼容,就中和一下了,在块级作用域中声明函数,类同var,在块级作用域以外,可以被访问调用,用几句代码说明吧,如下:
function f() {
console.log('I am outside!');
}
(function() {
if (true) {
// 重复声明一次函数f,类似于var,块级作用域外部可以访问函数
function f() {
console.log('I am inside!');
}
}
f(); //I am inside!
}());
另外,ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立。
const命令
const命令用于声明常量,本质上是指向地址不变,而非一个绝对的常量,所以如果是声明一个对象,对象内的属性是可以发生改变的,其他用法特性类似于let,只在所在的块级作用域内有效;变量不提升,会存在暂时性死区,只能在变量声明后的位置使用;不可重复声明;另,如果真想要不让某个对象发生变化,使用:const foo = Object.freeze({'a': 'tong'})。
顶层对象的属性
以前:var 声明的变量即为顶层对象的属性,
现在:let声明的变量与顶层对象无关。
global对象
- 浏览器里面,顶层对象是
window
,但 Node 和 Web Worker 没有window
。 - 浏览器和 Web Worker 里面,
self
也指向顶层对象,但是 Node 没有self
。 - Node 里面,顶层对象是
global
,但其他环境都不支持。
取顶层对象:
var getGlobal = function () {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};