文章目录
1. ES6 基础
1.1 ES6 是什么
ES6, 全称 ECMAScript 6.0
,是 JavaScript
的下一个版本标准
,2015.06 发版。
ECMA 是标准,JS 是实现
ES6
主要是为了解决 ES5
的先天不足。比如 JavaScript
里并没有类的概念
1.2 ES6兼容性
目前各大浏览器基本上都支持 ES6
的新特性,其中 Chrome
和 Firefox
浏览器对 ES6
新特性最友好,IE7~11
基本不支持 ES6。
Node
已经实现的 ES6
特性
1.2.1 如何解决兼容性问题?
针对 ES6
的兼容性问题,可以使用多种语法解析转换工具,把我们写的 ES6
语法转换成 ES5
,相当于在 ES6
和浏览器
之间做了一个翻译官。比较通用的工具方案有 babel
,jsx
,traceur
,es6-shim
等。
1.2.2 Babel
- Babel 入门教程 阮一峰
- Babel 是一个 JavaScript 编译器
- 一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行
- 现在就用 ES6 编写程序,而不用担心现有环境是否支持
2. 声明与表达式
2.1 let 和 const
- 不会被提升
- 不能重复声明
- 不绑定全局作用域
const
用于声明常量,其值一旦被设定不能再被修改,对于声明对象时,可以修改对象的值,但是不能修改引用对象的地址let
用于声明变量,其值能再被修改
2.1.1 var 存在的问题
- 可以重复声明。
- 无法限制修改。
- 声明全局变量时,会挂载在顶层对象(
window
)。 - 没有块级作用域,会出现变量提升,循环结束还可以访问到
i
的值。
var value;
if (false) {
value = 1;
}
console.log(value); // undefined
var value = 2;
console.log(window.value); // 2
for (var i = 0; i < 10; i++) {
...
}
console.log(i); // 10
变量提升:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部
2.1.2 Babel 中编译
1
let value = 1;
编译为
var value = 1;
2
if (false) {
let value = 1;
}
console.log(value); // Uncaught ReferenceError: value is not defined
编译为
if (false) {
var _value = 1;
}
console.log(value);
2.2 解构赋值
- 解构赋值是对赋值运算符的扩展。
- 他是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。
- 在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。
2.2.1 对象的解构赋值
通过 “{}” 去简化键值对取值的操作
let obj = {
username:'webpilot',
userid:12831,
profession:'webDeveloper',
region:'beijing'
}//同样还是这个数据
let {
username,userid,profession,region} = obj;
就是从obj里面取出前面花括号里面变量所对应的值,并且对应的赋值给花括号里面的对象。
使用冒号设置别名
let {
username:n} = obj;
通过等号设置默认值
let {
username:n} = obj;
2.2.2 数组的解构赋值
对象用的是 “{}” 而数组要用 “[]” 中括号
let arr = ['a','b','c','d','e','f','g'];
let [first,second,third] = arr;
console.log(first,second,third);//a b c
2.2.3 参数展开符
参数扩展/展开 ...args
- 收集剩余的参数,必须当到最后一个参数位置
- 展开数组,简写,效果和直接把数组的内容写在这儿一样
- 默认参数
function show(a, b, ...args) {
console.log(a)
console.log(b)
console.log(args)
}
console.log(show(1, 2, 3, 4, 5))
let arr1 = [1, 2, 3]
let arr2 = [4, 5, 6]
let arr3 = [...arr1, ...arr2]
console.log(arr3)
function show2(a, b=5, c=8) {
console.log(a, b, c)
}
show2(88, 12)
2.3 Symbol
ES6 引入了一种新的原始数据类型 Symbol
,表示独一无二的值。
1.Symbol()
函数会返回symbol
类型的值,使用 typeof,结果为 “symbol”
var s = Symbol();
console.log(typeof s); // "symbol"
2.Symbol 是一个原始类型的值,不能使用 new
命令,不能使用instanceof
判断其类型
3.Symbol
函数可以接受一个字符串作为参数,表示对 Symbol
实例的描述
4.如果 Symbol
的参数是一个对象,就会调用该对象的 toString
方法,将其转为字符串
5.Symbol
函数的参数只是表示对当前 Symbol
值的描述,相同参数的 Symbol
函数的返回值是不相等的。
6.Symbol
值不能与其他类型的值进行运算
7.Symbol
值可以作为标识符,用于对象的属性名,可以保证不会出现同名的属性
var mySymbol = Symbol();
// 第一种写法
var a = {
};
a[mySymbol] = 'Hello!';
// 第二种写法
var a = {
[mySymbol]: 'Hello!'
};
// 第三种写法
var a = {
};
Object.defineProperty(a, mySymbol, {
value: 'Hello!' });
// 以上写法都得到同样结果
console.log(a[mySymbol]); // "Hello!"
8.Symbol
作为属性名,该属性不会出现在 for...in
、for...of
循环中,也不会被 Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。但是,它也不是私有属性,有一个 Object.getOwnPropertySymbols
方法,可以获取指定对象的所有 Symbol
属性名。
var obj = {
};
var a = Symbol('a');
var b = Symbol('b');
obj[a] = 'Hello';
obj[b] = 'World';
var objectSymbols = Object.getOwnPropertySymbols(obj);
console.log(objectSymbols);
// [Symbol(a), Symbol(b)]
3. 内置对象
3.1 Map 与 Set
3.1.1 Map 对象
Map
对象保存键值对。任何值
(对象或者原始值) 都可以作为一个键或一个值
3.1.2 Maps 和 Objects 的区别
- 一个
Object
的键只能
是字符串
或者Symbols
,但一个Map
的键可以是任意值
。 Map
中的键值是有序
的(FIFO 原则),而添加到对象中的键则不是。Map
的键值对个数可以从size
属性获取,而 Object 的键值对个数只能手动计算。Object
都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
3.1.3 Set 对象
Set
对象允许你存储任何类型的唯一值
,无论是原始值或者是对象引用。
// 数组去重
var mySet = new Set([1, 2, 3, 4, 4]);
[...mySet]; // [1, 2, 3, 4]
// 并集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var union = new Set([...a, ...b]); // {1, 2, 3, 4}
3.2 Proxy 与 Reflect
Proxy
与 Reflect
是 ES6
为了操作对象引入的 API 。
Proxy
可以对目标对象的读取
、函数调用
等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式
,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。
Reflect
可以用于获取目标对象的行为,它与 Object
类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与 Proxy
是对应的。
3.2.1 Proxy
一个 Proxy
对象由两个部分组成: target
、 handler
。
target
即目标对象, handler
是一个对象,声明了代理 target
的指定行为。
let exam ={
name: "Tom",
age: 24
}
let proxy = new Proxy(exam, {
get(target, propKey, receiver) {
console.log('Getting ' + propKey);
return target[propKey];
}
set(obj, prop, value) {
if (prop === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('The age is not an integer');
}
if (value > 200) {
throw new RangeError('The age seems invalid');
}
}
// 对于满足条件的 age 属性以及其他属性,直接保存
obj[prop] = value;
}
})
proxy.name
// Getting name
// "Tom"
3.2.2 Reflect
ES6
中将 Object
的一些明显属于语言内部的方法移植到了 Reflect
对象上(当前某些方法会同时存在于 Object
和 Reflect
对象上),未来的新方法会只部署在 Reflect
对象上。
Reflect
对象对某些方法的返回结果进行了修改,使其更合理。
Reflect
对象使用函数的方式实现了 Object
的命令式操作。
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver