ES6 ES2015是主要的版本
ES2018 增加了rest和spread语法
ES2020 第11版
ES的下一个版本是ESnext
## ES6及以后新增常用API
#### let const
for (var i=0;i<=3;i++) {
setTimeout(function(){
console.log(i)
},10)
}
原因:
1、var 全局变量,只有一个i
2、setTimeout,下一轮事件循环的时候执行,i=4;console.log(4)
for (let i=0;i<=3;i++) {
setTimeout(function(){
console.log(i)
},10)
}
1、let 引入了块级作用域概念,创建setTimeout的时候,变量i只在作用域内生效。对于循环的每一次,引用的i都是不同的
for (let i=0;i<=3;i++) {
(function(i){
setTimeout(function(){
console.log(i)
},10)
})(i)
}
2、变量提升问题
console.log(i)
var i = 1;
// let i = 1; // 报错
3、const 常量
const i = 1;
// i=2 // 报错
#### 箭头函数
1、箭头函数的this是在什么位置定义决定的,普通函数的this是在使用的时候决定的
const obj = {
name: "123",
getName1: () => {
return this.name // window.name
},
getName2: function() {
return this.name // obj.name
}
}
2、简写
const arrow = (value) => Number(value)
相当于
const arrow = function(value) {
return Number(value)
}
const arrow = (value) => ({}) // 返回对象
3、箭头函数不能被用作构造函数
构造函数:改变this指向,指向新实例。
箭头函数:this是在定义的时候决定的。
#### class
class Test {
_name = '';
constructor(name) {
this.name = name
}
static getF() {
return `$(this.name)123123`
}
get name(val) {
return `${this._name} - 加一层包装`;
}
set name() {
console.log("检测到了name的赋值操作");
this._name = val;
}
}
const instance = new Test('ww') // 实例属性
console.log(instance.name)
console.log(Test.getF()) // 静态属性
#### 模板字符串
const a = '111\n222'
const b = `111
222`
render函数实现template的功能
const year = "2022";
const month = "10";
const day = "01";
const template = '${year}-${month}-${day}'
const context = {year, month, day}
const str = render(template)(context)
console.log(str) // 2020-10-01
function render(template) {
return function(context) {
return template.replace(/\$\{(.*?)\}/g, (match, key) => context[key]);
}
}
#### 解构
1、数组 // 找索引
let arr = [1,2,3]
let [a,b,c] = [1,2,3]
let [a,b,c] = [{
name:'1'
},{
name:'2'
}]
console.log(a.name,b.name)
2、对象 // 找值
const {a1, a2} = {a1:"123", a2: "456"}
console.log(a1, a2)
3、解构的原理
针对可迭代对象Iterator,通过遍历按照顺序获取对应的值进行赋值
3.1 Iterator 是什么
Iterator是一种接口,interface,为各种不一样的数据解构提供统一的访问机制
任何数据解构只要有Iterator接口
for of,相当于一个遍历器,遍历数据的时候,去寻找Iterator
const obj = {name: "123"}
for(n of obj){console.log(n)} // 报错:VM146:2 Uncaught TypeError: obj is not iterable
对象里没有 iterable
3.2 Iterator 有什么用呢
###### 为各种不同的数据解构提供统一的访问接口
###### 数据解构按照顺序处理
###### for of 可以进行遍历
let nextIndex = 0;
function generateIterator(array) {
return {
next: () => nextIndex < array.length ? {
value: array[next++],
done: false
} : {
value: undefined,
done: true
}>
}
}
const iterator = generateIterator([1,2,3])
console.log(iterator.next())
console.log(iterator.next())
value done
3.3 可迭代对象是什么
是Iterator接口的实现
可迭代对象存在两种协议,可迭代协议,迭代协议
可迭代协议:对象必须实现iterator方法,对象或者原型链上必须有一个Symbol.iterator:()=>迭代器协议
迭代器协议:必须实现一个next方法,next方法返回的对象done value
const obj = {
count: 0,
[Symbol.iterator]: () => {
return {
next: () => {
obj.count++;
if ( obj.count <= 10>) {
return {
value: obj.count,
done:false
}
} else {
return {
value: undefined,
done: true
}
}
}
}
}
}
for (let item of obj) {
console.log(item)
}
#### 遍历
1、for in
Object.prototype.moreName = 'ppppp';
let arr = [a,b,c]
let arr = {
a: 1,
b: 2
}
for (let item in arr) {
console.log(item) // 数组输出索引;对象输出key
if (item.hasOwnProperty) {
}
}
不仅会遍历当前对象,还遍历原型链上的属性
不适合遍历数组
forEach 不会被break中断
2、for of
const arr = [
{age: 12},
{age: 22},
{age: 32},
]
for (let {age} of arr) {
if (age > 20) {
break;
}
console.log(age)
}
#### Object
1 Object.keys 拿到的是key的数组
const obj = {
a:1,b:2
}
console.log(Object.keys(obj))
function getObjectKeys(obj) {
const result = [];
for(const key in obj) {
if (obj.hasOwnProperty(key)) {
result.push(key);
}
}
return result;
}
2 Object.values
const obj = {
a:1,b:2
}
console.log(Object.values(obj))
function getObjectValues(obj) {
const result = [];
for(const key in obj) {
if (obj.hasOwnProperty(key)) {
result.push(obj[key]);
}
}
return result;
}
3 Object.entries // 键值对的数组
const obj = {
a:1,b:2
}
console.log(Object.values(obj))
function getObjectEntries(obj) {
const result = [];
for(const key in obj) {
if (obj.hasOwnProperty(key)) {
result.push([key, obj[key]]);
}
}
return result;
}
4 Object.getOwnPropertyName // 获取对象自身的key,不包括原型
5 Object.getOwnPropertyDescriptor // 是对象属性的描述符,是一个对象
configurable // false时,其他属性都不可改
writable
'use strict'
enumerable // for in/Object.keys
get set
const obj = {};
let val = undefined;
Object.defineProperty(obj, 'a', {
set: function (value) {
console.log(`${value} - xxx `)
val = value;
},
get: function () {
},
configurable: true
})
obj.a = 111;
console.log(obj.a)
const obj = new Proxy({}, {
get: function (target, propKey) {
console.log(`invoke getter ${propKey}`)
return target[propKey]
},
set: function (target, propKey, value) {
console.log(`invoke setter ${propKey} ${value}`)
return Reflect.set(target, propKey, value);
}
})
obj.s = 1;
console.log(obj.s)
Reflect 是什么?
语言的优化,内部方法移动到Reflect上
命令式的行为变成函数式的
const obj = {name:1}
delete obj.name // 命令
Reflect.deleteProperty(obj, name) 函数
6 Object.assign // 浅拷贝 {...a, ...b}
const newObj = obj.assign({}, {
name: '11',
age: '22'
}, {
name: '333' // 后面覆盖前面
})
console.log(newObj)
function shallowClone(source) {
const target = {};
for (const i in source) {
if (source.hasOwnProperty[i]) {
target[i] = source[i];
}
}
return target;
}
Promise Promise.allSettled // 返回所有promise的状态和结果
function PromiseAllSettled(promiseArray) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promiseArray)) {
return reject(new TypeError('参数必须是一个数组'))
}
let counter = 0;
const promiseNum = promiseArray.length;
const resolvedArray = [];
for (let i = 0; i < promiseNum; i++) {
Promise.resolve(promiseArray[i]).then(value => {
resolvedArray[i] = {
status: 'fulfilled',
value
}
})
.catch(reason => {
resolvedArray[i] = {
status: 'rejected',
reason
}
})
.finally(() => {
counter++;
if (counter == promiseNum) {
resolve(resolvedArray)
}
})
}
})
}
#### 数组
1. Array.flat(arr, deep)
const arr1 = [1, 2, [3, 4, [5]]];
console.log(arr1.flat(1))
console.log(arr1.flat(Infinity))
function flatDeep(arr, d = 1) {
if (d > 0) {
return arr.reduce((res, val) => {
if (Array.isArray(val)) {
res = res.concat(flatDeep(val,d - 1))
} else {
res = res.concat(val);
}
return res;
}, [])
} else {
return arr.slice();
}
}
flatDeep(arr1, Infinity)
2. Array.includes
const arr = [1,2,3]
console.log(arr.includes(2))
3. Array.from // 如何把一个类数组转换成真数组。
console.log(Array.from([1, 2, 3], x => x + 1))
// 如何把arguments转换成真数组。
1 [...arguments]
2 Array.from(arguments)
3 Array.prototype.slice.call(arguments)
# babel编译工具链的使用
//astexplorer.net 查看AST
1、解析
接受代码输出AST
*词法分析
*语法分析
2、转换
接受AST对其进行遍历,可以对节点进行添加 更新 移除等操作
3、生成
把转换过的AST生成为字符串形式的代码,并且创建source map
plugins.js
const template = require('babel-template')
const temp = template('var b=1');
module.exports = function ({
types: t
}) {
return {
visitor: {
VariableDeclaration(path, state) { // 变量声明
// 找到AST节点
const node = path.node;
if (t.isVariableDeclaration(node, {
kind: 'const'
})) {
node.kind = 'let';
const inserNode = temp();
path.inserBefore(inserNode);
}
}
}
}
}
babel.js
const myPlugin = require("./plugin");
const babel = require('@babel/core');
const constent = 'const name = 123';
const { code } = babel.transform(content, {
plugins: [myPlugin]
})
console.log(code)