ES6
1.ES6介绍
- ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言
ES6既是一个历史名词,也是一个泛指,含义是 5.1 版以后的JavaScript 的下一代标准,涵盖了
ES2015、ES2016、ES2017 等等,而 ES2015 则是正式名称,特指该年发布的正式版本的语言标准。本书中提到
ES6的地方,一般是指 ES2015 标准,但有时也是泛指“下一代 JavaScript 语言”
90%的浏览器都支持ES6,也可以通过babel 编译器(一个 js 编译器)将 ES5 代码 转为
2.let var 和const 区别
- let 声明变量没有变量提升,var 有变量提升
- let 是一个块作用域, let声明的变量只在它所在的代码块有效。
- let 不可以重复声明,var 可以重复
- const 声明常量,一旦声明就不能被修改,除此之外也有 let 的三个特性。
- 建议:开发中,默认情况下用 const,而只有在你知道变量值需要被修改的情况下使用 let
for循环中使用let,因为var存在变量提升
3.模板字符串
- 模板字符串:使用 tab 键的反引号 `
- 插入变量时:使用 ${ 变量名 }
4.剩余参数
- 由…和一个紧跟着的具名参数组成 : …keys
- …keys 解决了 arguments 的问题
function checkArgs(...args){
console.log(args); // 返回一个真实的实参数组["a", "b", "c"]
console.log(arguments); // 返回一个实参伪数组
}
checkArgs('a','b','c');
5.扩展运算符
剩余参数与扩展运算符的区别:
- 剩余参数:把多个独立的合并到一个数组中
- 扩展运算符:将一个数组分割,并将各个项作为分离的参数传给函数
// Math.max 获取最大值
const arr = [10, 20, 50, 30, 90, 100, 40];
// 扩展运算符更方便
console.log(Math.max(...arr)) // 100
6. 解构赋值
- 解构赋值是对赋值运算符的一种扩展。它通常针对数组和对象进行操作。
- 优点:代码书写简洁且易读性高
// 例 1 对对象的解构
// 完全解构
let node = {
type:'iden',
name:'foo'
}
let {type,name} = node;
console.log(type,name) //iden foo
// 不完全解构
let obj = {
a:{
name:'张三'
},
b:[],
c:'hello world'
}
//可忽略 忽略b,c属性
let {a} = obj;
//剩余运算符 使用此法将其它属性展开到一个对象中存储
let {a,...res} = obj;
console.log(a,res);
// 默认值 a 的值 20 ,b 的值 30
let {a,b = 30} = {a:20};
// 例 2 对数组的解构
let [a, b] = [1, 2, 3];
console.log(a,b)
//可嵌套
let [a, [b], c] = [1, [2], 3];
7.扩展的对象功能
对象的方法:
Object.is()
is() 和 ===
比较两个值是否严格相等
ES5 比较两个值是否相等,只有两个运算符:相等运算符()和严格相等运算符 (=)。它们都有缺点,前者会自动转换数据类型,后者的NaN不等于自身,以及+0等 于-0。JavaScript
缺乏一种运算,在所有环境中,只要两个值是一样的,它们就应该相等。ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。Object.is就是 部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
Object.assign()
Object.assign(target, obj1, obj2…)方法用于对象的合并,将原对象(obj)的所有属性,复制到目标对象(target)。
// 例 1
const name = '张三';
const age = 19;
const person = {
name, //等同于name:name
age,
// 方法也可以简写
sayName() {
console.log(this.name);
}
}
person.sayName();
// 例 2
function getPoint() {
const x = 1;
const y = 10;
return {x, y};
}
getPoint()
// {x:1, y:10}
// 对象的方法:
// is() 和 ===
// 比较两个值是否严格相等
console.log(NaN === NaN); // false ,===有缺陷
console.log(Obejct.is(NaN, NaN)); // true
// assign()
// 对象的合并 浅拷贝
let newObj = Object.assign({}, {a: 1}, {b: 2});
console.log(newObj); // {a: 1, b: 2}
8.Symbol
- 它表示的是独一无二的值
- 最大的用途:用来定义对象的私有变量
- 如果用 Symbol 定义的是对象中的变量,取值时一定要用 [变量名]
- 如果用 Symbol 定义的是对象中的变量,该变量不能作为key,无法用 for 循环遍历
注意: *这个数据类型实际开发中用的不多*
const name = Symbol('name');
const name2 = Symbol('name');
console.log(name === name2); // false
// 用来定义对象的私有变量
let s1 = Symbol('s1');
console.log(s1);
let obj = {};
obj[s1] = '牛肉粉'; // 等价于 obj = { [s1]: '牛肉粉' }
//如果用 Symbol 定义的是对象中的变量,取值时一定要用 [变量名]
console.log(obj[s1]);
console.log(obj.s1); // 会报错
如果用 Symbol 定义的是对象中的变量,该变量不能作为key,无法用 for 循环遍历
for(let key in obj){
console.log(key); // 没有输出
}
console.log(Object.keys(obj)); // 输出一个空数组 []
9.Map和Set方法
(1)set
Set 集合:表示无重回复值的有序列表
console.log(set)//会有很多方法 是个对象
let set = new Set();
// 添加元素 add()
set.add(2);
set.add('4');
set.add('4'); // 这个4会被忽略,因为集合表示无重回复值的有序列表
console.log(set); // set(2) {2, "4"}
// 也可以添加数组
set.add([1, 2, 3]);
// 删除元素 delete()
set.delete(2);
console.log(set);
// 校验某个值是否在 set 中 has()
console.log(set.has('4')); // 返回 true
// 访问集合的长度
console.log(set.size);
// set 转换成 数组
let set2 = new Set([1, 2, 3, 4]);
// 使用扩展运算符
let arr = [...set2];
console.log(arr);//[1,2,3,4]
(2)Map
Map:键值对的有序列表,键和值是任意类型
let map = new Map();
// set() 设置值
map.set('name', '张三');
map.set('age', '20');
console.log(map); // 输出 { 'name' => '张三', 'age' => '20'}
// 键和值可以是任意类型
map.set(['a', [1, 2, 3]], 'hello');
// get() 获取值
console.log(map.get('name')); //张三
// has() 校验某个值是否在 map 中
console.log(map.has('name')); //true
// delete() 删除值
map.delete('name');
// clear() 清除所有值
map.clear();
10数组的扩展
Array.from()方法用于将伪数组转为真正的数组
// Array.from()方法用于将伪数组转为真正的数组
function add() {
// ES5 的写法,不宜阅读
var arr1 = [].slice.call(argumets); // [1, 2, 3]
console.log(arr1);
// ES6 的写法
let arr2 = Array.from(argumets); // [1, 2, 3]
console.log(arr2);
}
add(1, 2, 3);
// 方法二:使用扩展运算符, 将伪数组转为真正的数组
// querySelectorAll()方法返回的是一个类似数组的对象
let lis = document.querySelectorAll('li');
console.log([...lis]);
// Array.from()方法还可以接受第二个参数,对每个元素进行处理
let lis = document.querySelectorAll('li');
let names2 = Array.from(lis, s => s.textContent);
console.log(names2);
Array.of()方法用于将一组值,转换为数组
Promise
- 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果
- Promise 是一个对象,Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。axios 的内部实现原理就是通过 Promise 实现的
- Promise对象有以下两个特点:
1.对象的状态不受外界影响。有三种状态:pending(进行中)、fulfilled(成功)和rejected(失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
2.一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为resolved和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果- Promise对象是一个构造函数,用来生成Promise实例,带有一个回调函数,回调函数的两个参数是 resolve(成功)和reject(失败),这两个参数他们也是函数。
- then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,它们都是可选的。
基本使用:
function timeOut(ms){
// Promise对象是一个构造函数,用来生成Promise实例
return new Promise((resolve, reject) => { // 闭包函数:一个函数里面返回一个函数
// ... 模拟执行异步操作,后端返回的数据
let res = {
// code: 200,
code: 201,
data:{
name: '牛肉粉'
},
error: '失败了';
}
setTimeout(() => {
// 异步执行成功
if (res.code === 200){
resolve(res.data);
// 异步执行失败
} else {
reject(res.error);
}
}, ms);
});
}
// then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,它们都是可选的。
timeOut(2000).then((val) => {
// success
console.log(val); //这里的值接收的是 resolved() 的值,输出 {name: "牛肉粉"}
}, (err) => {
// failure
console.log(err); //这里的值接收的是 rejected() 的值,输出 失败了
});
async
async 函数,它就是 Generator 函数的 语法糖
作用:使得异步操作更加方便
异步操作是JavaScript编程的麻烦事,很多人认为async函数是异步编程的解决方案
- 凡是在前面添加了async的函数在执行后都会自动返回一个Promise对象
async function test() {
}
let result = test()
console.log(result) //即便代码里test函数什么都没返回,我们依然打出了Promise对象
- await必须在async函数里使用,不能单独使用
- await的作用之一就是获取后面Promise对象成功状态传递出来的参数传给 then
函数。
es6的模块化
- ES6 模块功能主要有两个命令构成:export 和 import
- export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
- 一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量