ES6新特性(上)
- let和const命令
- es6的模板字符串
- 增强的函数
- 解构赋值
- 扩展的字符串、对象、数组功能
- Symbol
- Map和Set
- 迭代器和生成器
- Promise对象
- Proxy对象
- async的用法
- 类 class
- 模块化实现
参考链接:
9~13章请看→ES6新特性(下)篇:https://wuyea.top/posts/2559352444.html
1. let和const命令
let命令
特性:
- 不存在变量提升。
- 只在let命令所在的代码块内有效。
- 不能重复声明。
- 不会污染全局变量。
const命令
特性:
- const的作用域与let命令相同:只在声明所在的块级作用域内有效。
- 一旦声明变量,就必须立即初始化,且不可更改。
2. 模板字符串
模板字符串:使用tab键上面的反引号``
, 插入变量时使用 ${变量名}
。
示例:
<html>
<head>
<title>模板字符串</title>
</head>
<body>
<div class="box">
</div>
<script>
const oBox = document.query.Selector('.box');
let id=1,name="wuye";
let htmlStr = `<ul>
<li>
<p id=${id}>${name}</p>
</li>
</ul>`;
oBox.innerHTML = htmlStr;
</script>
</body>
</html>
3. 增强的函数
函数参数的默认值
示例:
function add(a, b=20){
return a + b;
}
console.log(add(30));
默认的表达式也可以是一个函数
function add(a, b=getVal(5)){
return a + b;
}
function getVal(val){
return val + 5;
}
console.log(add(10));
剩余运算符
解释:把多个独立的参数合并到一个数组中。
使用:由三个点…和一个紧跟着的具名参数指定 …keys
function pick(obj, ...keys) {
// ...keys 解决了 arguments 的问题
let result = Object.create(null);
for(let i=0;i< keys.length; i++) {
result[keys[i]]= obj[keys[i]];
}
return result;
}
let book = {
title:'es6的教程',
author:'wuye',
year:2024
}
let bookData = pick(book, 'year', 'author');
console.log(bookData);
function checkArgs(...args) {
console.log(args);
console.log(arguments);
}
checkArgs('a', 'b', 'c');
扩展运算符
解释:将一个数组分割,并将各个项作为分离的参数传给函数
const arr = [10,20,50,40,90,100];
console.log(Math.max.apply(null, arr)); // es5写法
console.log(Math.max(...arr)); // es6的扩展运算符
箭头函数
使用 =>
来定义,取代了 function(){}
,等价于 ()=>{}
示例1:
let add = function(a, b) { // es5
return a + b;
}
let add = (a, b) => { // es6
return a + b;
}
console.log(add(10,20));
示例2:
let add = val => {
return val + 5;
}
// 上面的等价与下面
let add = val => (val + 5); // (val + 5) 就是 {return val+5}
let add = val => val; // 等价于:let add = val=>(val); 也可以省略小括号
console.log(add(10));
let add = (val1, val2) => val1 + val2;
console.log(add(10, 20));
// 如果没有参数
let fn = () => 'hello world' + 123;
console.log(fn());
let getObj = id => ({id:id, name:"wuye"}); // 此时一定需要小括号
let obj = getObj(1);
console.log(obj);
箭头函数中的this指向
注意:箭头函数没有this指向,箭头函数内部this只能通过查找作用域链来确定,一旦使用箭头函数,当前就不存在作用域链
使用箭头函数的注意事项
使用箭头函数,函数内部没有arguments。
箭头函数不能使用new关键字来实例化对象。
function函数 也是一个对象,但是箭头函数不是一个对象,它其实就是一个语法糖。
4. 解构赋值
解构赋值是对赋值运算符的一种扩展,它针对数组和对象来进行操作。
优点:代码书写上简洁易读。
示例一:完全解构
let node = {
type: 'iden',
name: 'foo'
}
// es5写法:
// let type = node.type;
// let name = node.name;
// es6写法:
let {type, name} = node;
console.log(type, name)
示例二:不完全解构,可忽略
let obj = {
a: {
name: "张三"
},
b: [],
c: "hello world"
}
let {a} = obj; // 不能写成 let {f} = obj, 不支持对名称重命名
console.log(a);
// 剩余运算符
let {a, ...res} = obj;
console.log(res);
示例三:对数组解构
let arr =[1,2,3];
let [a,b]= arr;
console.log(a,b);
// 可嵌套
let [a,[b],c]=[1,[2],3];
// 默认值: a=20, b=30
let {a, b=30} = {a:20};
5. 扩展的对象功能
es6直接写入变量和函数,作为对象的属性和方法
示例一:
const name='wuye', age='18';
const person = {
name, // 等价于 name:name
age, // 等价于 age:age
[name + '_bak'] = 'wuye', // 等价于 wuye_bak='wuye', [name+'_bak']就是字符串拼接
sayName() { // 等价于 sayName: function()
console.log(this.name);
}
}
person.sayName();
示例二:
// is() === 比较两个值是否严格相等
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true
// assign() 对象的合并
// Object.assign(target, obj1, obj2......)
let newObj = Object.assign({}, {a:1}, {b:2}); // 返回合并之后的新对象
console.log(newObj); // {a:1, b:2}
6. Symbol类型
原始数据类型Symbol,它表示是独一无二的值(内存地址不相同)。
如果用Symbol定义的对象中的变量,取值时一定要用 [变量名]
。
最大用途:用来定义对象的私有变量。
const name = Symbol('name');
const name2 = Symbol('name');
console.log(name === name2); // false 因为内存地址不相同
let s1 = Symbol('s1');
let obj = {[s1]: 'wuye'}
console.log(obj[s1]) // wuye
console.log(obj.s1) // undefined
//获取Symbol声明的属性名(作为对象的key)
let s = Object.getOwnPropertySymbols(obj);
console.log(s[0]);
let m = Reflect.ownKeys(obj);
console.log(m[0]);
7. Map和Set
Set
集合:表示无重复值的有序列表
let set = new Set(); // 创建空集合
console.log(set);
//添加元素
set.add(2);
set.add([1,2,3]);
// 删除元素
set.delete(2);
// 校验某个值是否在set中
set.has('4')
// 通过扩展运算符将set转化为数组
let set2 = new Set([1,2,3,3,3,4]);
let arr = [...set2]
console.log(arr);
(非重点)因为set无法释放对象,所以有 WeakSet,但是需要注意:
- 不能传入非对象类型的参数
- 不可迭代
- 没有forEach()
- 没有size属性
/* let set3 = new Set(), obj={};
set3.add(obj);
obj = null; // 释放当前的资源
console.log(set3); */
let set4 = new WeakSet(), obj = {};
set4.add(obj);
obj = null; // 释放当前的资源
console.log(set4);
Map
Map类型是键值对的有序列表,键和值是任意类型。
let map = new Map();
map.set('name','张三');
map.set('age',20);
console.log(map.get('name'));
console.log(map);
map.has('name'); // true
8. 迭代器和生成器
迭代器 Iterator
Iterator是es6引入的一种新的遍历机制。两个核心:
- 迭代器是一个统一的接口,它的作用是使各种数据结构可被便捷的访问,它是通过一个键为Symbol.iterator 的方法来实现。
- 迭代器是用于遍历数据结构元素的指针(如数据库中的游标)。
// 使用迭代
// 1.使用Symbol.iterator创建一个迭代器
// const items = ['one','two','three'];
// // console.log(items);
// const it = items[Symbol.iterator]();
// console.log(it);
// 2.调用next方法向下迭代,next方法会返回当前的位置
// const nextEle = it.next();
// 3.当done为true时则遍历结束
// console.log(nextEle);
// 可迭代的数据结构
// Array String MaSet
// 但是对象是不能迭代
// 跟迭代紧密相关的就是for...of循环
// for(let item of items){
// console.log(item);
// }
// 将对象转换成数组
const arrayLink = {length: 2, 0: "zero", 1: "one"}
console.log(Array.from(arrayLink));
for(let item of Array.from(arrayLink)){
console.log(item);
}
生成器 Generator
es6新引入了Generator函数,可以通过yield关键字,把函数的执行流挂起,为改变执行流程提供了可能,从而也为了异步编程提供了解决方案。
它跟普通函数的区分:
- 在function后面,函数名之前有个*
- 函数内部有yield(产出)表达式
// *表示函数为Generator函数,
function* func(a) {
console.log('one');
yield a;
console.log('two');
yield '2';
console.log('three');
return 3;
}
// 每次执行函数都会返回一个遍历器对象
let fn = func(1); // 此时函数不会真的执行,只是返回一个遍历器对象
console.log(fn);
// 必须调用遍历器对象的next方法,使得指针移向下一个状态
// console.log(fn.next());
// console.log(fn.next());
// console.log(fn.next());
// 总结: Generator函数是分段执行的,yield语句是暂停执行,而next方法可以恢复执行
function* add() {
console.log('start');
// x 可真的不是yield '2'的返回值,它是next()调用 恢复当前yield()执行传入的实参
var x = yield '2';
console.log('one:' + x);
var y = yield '3';
console.log('two:' + y);
console.log('total:' + (x + y));
return x+y;
}
const a = add();
console.log(a.next()); // {value:'2', done:false}
console.log(a.next(20)); // {value:'3', done:false}
console.log(a.next(30)); // {value:50, done:true}
使用场景:为不具备Interator接口的对象提供了遍历操作
// 使用场景,为不具备Interator接口的对象提供了遍历操作
function* objectEntries(obj) {
// 获取对象的所有key 存储到数组中
const propKeys = Object.keys(obj);
// console.log(propKeys);
for (const propKey of propKeys) {
yield [propKey, obj[propKey]];
}
}
const obj = {
name: 'Jane',
age: 18
}
obj[Symbol.iterator] = objectEntries;
console.log(obj);
for (const [key, value] of objectEntries(obj)) {
console.log(`${key}: ${value}`);
}