一、 es6提出了许多新的语法:下面接着介绍:
- let 、const 命令:
- 变量的解构赋值
- 运算符的扩展
在es5中我们声明变量的方式只有一种,就是通过var。es6新增了两种声明变量的方式。
1.1 //通过let的方式声明变量
console.log(name); //Uncaught ReferenceError: Cannot access 'name' before initialization
let name = "yz";
console.log(name); //yz
- let方式声明的变量不存在变量提升,只在当前的代码块有效。
for (let i = 5; i < 10; i++) {
//通过let声明的变量只在当前的for循环有效,外面打印不出来会报错
}
console.log(i);//Uncaught ReferenceError: i is not defined
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6]();
//无论调用那个数组的数字打印结果都是10,说明var声明的变量是全局的,
//每次都是指向全局的同一个变量。
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6]();
//换成let当前的变量i只在本轮循环有效,每次i都是一个新的变量,所有打印的结果是正常。
可以看出内部循环变量i和循环变量i不在同一个作用域。不然i不能输出5次,也可以看出循环体是一个单独的作用域。
设置循环的部分也是一个单独的作用域。
for (let i = 0; i < 5; i++) {
let i = 666;
console.log(i); //输出5次 666
}
2.存在暂时性死区和不能重复声明、以及存在块级作用域
//通过let的方式声明变量,存在暂时性死区。以及不能重复声明和存在块级作用域
var temp = "123";
if (true) {
temp = "456";
let temp
}
console.log(temp);//test.html:14 Uncaught ReferenceError: Cannot access 'temp' before initialization
上面声明了全局tmep 在块内部又声明了temp,使得其存在了块级作用域,在声明之前对其赋值导致报错。
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
if (true) {
x=5
console.log(x); //会报错,let声明变量不存在提升,存在暂时性死区,未声明去使用会报错。
let x;
}
暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
let x=5
let x=6
console.log(x);//Uncaught SyntaxError: Identifier 'x' has already been declared
不允许重复声明
es5中只存在全局作用域和函数作用域,会有下面的问题
1.內部的变量会覆盖外部的变量
var name = "yz";
function fn() {
console.log(name);
if (true) {
var name = "hello";
}
}
fn(); //undefined //导致变量提升,内部变量覆盖外部变量
//存在块级作用域输出结果为5
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
f1()
2.块级作用域和函数声明
ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
1.2 通过const的方式声明常量:
//const声明的常量值不能在变,const也存在块级作用域和暂时性死区,以及不能重复声明
const a = 6;
a = 5555;
console.log(a); //test.html:12 Uncaught TypeError: Assignment to constant variable.
const声明常量的本质:
对于基本数据类型它们保存在栈内存中,它们的地址就是他们的值,所以我们不能变值,对于复杂类型的数据,他们保存在堆内存中,我们只是通过指针指向它的地址。只要指针的指向不变就行,为其添加或者删除值都是可以的。
1.3 javaScript的global对象:
javaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。但是,顶层对象在各种实现里面是不统一的。
浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。
浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。
Node 里面,顶层对象是global,但其他环境都不支持。
同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this关键字,但是有局限性。
全局环境中,this会返回顶层对象。但是,Node.js 模块中this返回的是当前模块,ES6 模块中this返回的是undefined。函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。不管是严格模式,还是普通模式,new Function(‘return this’)(),总是会返回全局对象。但是,如果浏览器用了 CSP(Content Security Policy,内容安全策略),那么eval、new Function这些方法都可能无法使用。
很难找到一种方法,可以在所有情况下,都取到顶层对象。下面是两种勉强可以使用的方法。
// 方法一
(typeof window !== 'undefined'
? window
: (typeof process === 'object' &&
typeof require === 'function' &&
typeof global === 'object')
? global
: this);
// 方法二
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');
};
1.4 ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,还有import命令和class命令。所以,ES6 一共有 6 种声明变量的方法。