一个完整的JavaScript的实现由三个部分组成:
什么是 ES
ECMAScript(简称ES)是由ECMA-262定义的。
ES 与 JS
ES可以理解为是JavaScript的一个标准。实际上,JavaScript是ECMA-262标准的实现和扩展。
ES与Web浏览器
ES与浏览器没有依赖关系。 Web浏览器只是ES实现可能的宿主环境之一,其他宿主环境包括node和Adobe flash。
ES6即ECMAScript的第6版。
let的特性 let-Javascript MDN
var x = 'global'
let y = 'global'
console.log(this.x) // "global"
console.log(this.y) // undefined
var a = 1
var b = 2
if (a === 1) {
var a = 11 // the scope is global
let b = 22 // the scope is inside the if-block
console.log(a) // 11
console.log(b) // 22
}
console.log(a) // 11
console.log(b) // 2
var Thing
{
let privateScope = new WeakMap()
let counter = 0
Thing = function () {
this.someProperty = 'foo'
privateScope.set(this, {
hidden: ++counter,
})
}
Thing.prototype.showPublic = function () {
return this.someProperty
}
Thing.prototype.showPrivate = function () {
return privateScope.get(this).hidden
}
}
console.log(typeof privateScope) // "undefined"
var thing = new Thing()
console.log(thing) // Thing {someProperty: "foo"}
thing.showPublic() // "foo"
thing.showPrivate() // 1
// 在 switch 语句中只有一个块
let x = 1
switch (x) {
case 0:
let foo
break
case 1:
let foo // SyntaxError for redeclaration.
break
}
// 解决方法:一个嵌套在 case 子句中的块会创建一个新的块作用域的词法环境
let x = 1
switch (x) {
case 0: {
let foo
break
}
case 1: {
let foo
break
}
}
function do_something() {
console.log(bar) // undefined
console.log(foo) // ReferenceError
var bar = 1
let foo = 2
}
// 在同一行,这个if块中的foo已经在词法环境中被创建了,但是还没有到达(或者终止)它的初始化(这是语句本身的一部分)
// 这个if块里的foo还依旧在暂存死区里
function test() {
var foo = 33
{
let foo = foo + 55 // ReferenceError
}
}
test()
console.log(typeof undeclaredVariable) //打印出 undefined
console.log(typeof undeclaredVariable) //打印出 undefined
var varVariable
console.log(typeof i) //引发异常 ReferenceError: Cannot access 'i' before initialization
let i = 10
const声明一个只读的常量。一旦声明,变量指向的那个内存地址不得改动(不是变量值不能改变),且声明时必须立即初始化,不能留到以后赋值。const的作用域与let命令相同:只在声明所在的块级作用域内有效。
对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。
但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。如果真的想将对象或对象属性冻结,应该使用Object.freeze方法。
const foo = {}; // const foo = []同理,可以正常使用push等功能
foo.prop = 123; // 为foo添加一个属性,可以成功
console.log(foo.prop); //123
foo = {}; // 将foo指向另一个对象,就会报错
Class ES2015
类的数据类型就是函数,类本身就指向构造函数
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
let a = 1;
let b = 2;
let c = 3;
// 等价于
let [a, b, c] = [1, 2, 3];
let [ , third] = ["foo", "bar", "baz"];
third // "bar"
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // 变量解构不成功,赋值为undefined
z // 数组解构不成功,赋值为[]
解构赋值允许指定默认值,只有当一个数组成员严格等于undefined,默认值才会生效:
let [foo = true] = []; // foo = true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [q = 1, w = 'b'] = ['a', undefined]; // q='a', w='b'
let [e = 1] = [null]; // e = null