…
版本 兼容性 IE7~11 基本不支持 ES6。
ES 6
let const
箭头函数
模块化
Promise
面向对象
数组解构赋值
ES 7
幂运算符(**)
数组扩展:Array.prototype.includes() 用来判断一个数组是否包含一个指定的值
ES 8
async / await
字符串扩展
共享内存和Atomics:允许您在多个 workers 和主线程之间共享 SharedArrayBuffer 对象的字节
Object.values / Object.entries
String padding
Object.getOwnPropertyDescriptors()
函数参数列表和调用中的尾逗号
ES 9
对象解构赋值
异步迭代
Rest/Spread 属性
新的正则表达式功能
Promise.prototype.finally()
模板字符串修改
ES 10
扩展对象
数组方法
行分隔符(U + 2028)和段分隔符(U + 2029)符号现在允许在字符串文字中,与JSON匹配
更加友好的 JSON.stringify
新增了Array的flat()方法和flatMap()方法
新增了String的trimStart()方法和trimEnd()方法
Object.fromEntries()
Symbol.prototype.description
String.prototype.matchAll
Function.prototype.toString()现在返回精确字符,包括空格和注释
简化try {} catch {},修改 catch 绑定
新的基本数据类型BigInt
globalThis
import()
Legacy RegEx
私有的实例方法和访问器
Let 一般 var
没有块级作用域。
而let
不可重复声明,支持块级作用域,且不存在变量提升。
const 修改其元素和属性,不算对常量的修改。
解构赋值 解构赋值是对赋值运算符的扩展。
例如:
1 2 3 4 5 6 7 let [a, b, c] = [1 , 2 , 3 ];let [a, [[b], c]] = [1 , [[2 ], 3 ]];let [a, , b] = [1 , 2 , 3 ]; let [a = 1 , b] = []; let [a, ...b] = [1 , 2 , 3 ]; let [a, b, c, d, e] = 'hello' ;let { foo, bar } = { foo : 'aaa' , bar : 'bbb' };
Symbol 是一种新的数据类型,Symbol 表示独一无二的值,最大的用法是用来定义对象的唯一属性名。一个对象的键只能是字符串或Symbol。
1 2 3 4 let sy = Symbol ("key1" );let syObject = {};syObject[sy] = "kk" ; console .log (syObject);
不会出现在 for…in 、 for…of 的循环中,也不会被 Object.keys() 、 Object.getOwnPropertyNames() 返回。
如果要读取到一个对象的 Symbol 属性,可以通过 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到。
Symbol 也可以定义常量。
1 2 3 const COLOR_RED = Symbol ("red" );const COLOR_YELLOW = Symbol ("yellow" );const COLOR_BLUE = Symbol ("blue" );
其他方法:
1 2 3 4 Symbol .for ()Symbol .keyFor ()
迭代器 支持:
Array
Arguments
Set
Map
String
TypedArray
NodeList
1 2 3 for (let [key, val] of map){ }
适用于自定义遍历数据。
生成器 使用yield
关键字实现的函数。
1 2 3 4 5 6 7 8 9 function * fn (arg ) { let param1 = yield "1" ; let param2 = yield "2" ; let param3 = yield "3" ; } let iterator = fn ();iterator.next (param)
Map Set Map 是键值对:
键可以是任何值。
添加的键是有序的。
可以获取键值对数。
1 2 3 var map = new Map ();map.set (key, "" ) map.get (key)
遍历
1 2 3 4 5 6 for (var [key, val] of map){ } map.forEach (function (val, key ){ }, map)
Set 对象允许存储任何类型的唯一值,无论是原始值或者是对象引用。
1 2 3 4 5 6 7 let set = new Set ();set.add (1 ) var ix = new Set ([...a].filter (x => b.has (x)))var ix = new Set ([...a].filter (x => !b.has (x)))
Reflect Proxy Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。
一个 Proxy 对象由两个部分组成: target 、 handler 。在通过 Proxy 构造函数生成实例对象时,需要提供这两个参数。 target 即目标对象, handler 是一个对象,声明了代理 target 的指定行为。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 let target = { name : 'Tom' , age : 24 } let handler = { get : function (target, key ) { console .log ('getting ' +key); return target[key]; }, set : function (target, key, value ) { console .log ('setting ' +key); target[key] = value; }, apply : function (target, ctx, args ){ console .log ('handle apply' ); return Reflect .apply (...arguments ); }, has : function (target, propKey ){ console .log ("handle has" ); return propKey in target; }, construct : function (target, args, newTarget ) { console .log ('handle construct' ) return Reflect .construct (target, args, newTarget) } deleteProperty : null , } let proxy = new Proxy (target, handler)proxy.name proxy.age = 25
其他操作
ES6 中将 Object 的一些明显属于语言内部的方法移植到了 Reflect 对象上(当前某些方法会同时存在于 Object 和 Reflect 对象上),未来的新方法会只部署在 Reflect 对象上。
Reflect 对象对某些方法的返回结果进行了修改,使其更合理。
Reflect 对象使用函数的方式实现了 Object 的命令式操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let exam = { name : "Tom" , age : 24 , get info (){ return this .name + this .age ; } } let receiver = { name : "Jerry" , age : 20 } Reflect .get (exam, 'info' , receiver); Reflect .set (target, name, value, receiver)Reflect .has (obj, name)Reflect .deleteProperty (obj, property)Reflect .construct (obj, args)
实现观察者模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 const queuedObservers = new Set ();const observe = fn => queuedObservers.add (fn);const observable = obj => new Proxy (obj, {set});function set (target, key, value, receiver ) { const result = Reflect .set (target, key, value, receiver); queuedObservers.forEach (observer => observer ()); return result; }
字符串 新加入反引号用法
1 2 3 4 5 6 7 8 9 10 const str = ` <ul> <li>a</li> <li>${user} </li> </ul> ` str.trimStart () str.trimEnd ()
数组 常用方法
1 2 3 4 5 6 7 8 const arr = ['aa' , 'bb' , 'cc' ]if (arr.includes ('bb' )) { } arr.flat (2 ) arr.flatMap ()
函数 箭头函数
默认参数
1 function add (a, b, c=10 ) {}
rest 参数,用于代替arguments
1 2 3 4 5 6 7 function fn ( ) { console .log (arguments ); } function fn (...args ) { console .log (args); }
可选链操作符
1 2 const name = person.stu .name const name = person?.stu ?.name
对象 允许直接插入变量
1 2 3 4 const person = { name, age : 10 }
解对象操作
方法扩展
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Object .is (NaN === NaN )Object .assign (obj1, obj2)Object .setPrototypeOf (obj1, obj2)Object .keys (stu)Object .values (stu)Object .entries (stu) Object .create (null , { name : { value : '' , writable : true , configurable : true , enumerable : true } }) Object .getOwnPropertyDescriptors (stu)Object .fromEntries ([ ['name' , '123' ], ['age' , 123 ] ]) Object .fromEntries (new Map ())
ES 11 的私有属性
全局this
类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Person { static count = 10 ; constructor (name, age ) { this .name = name this .age = age } call ( ) { return this .name } get height () { return '10m' } set height (val ) { } } class Student extends Person { constructor (name, age ) { super (name, age) } } const stu = new Student ('jack' , 10 )
模块 当需要暴露数据时,只需要在前面写export
1 2 export const str = '123' export function test ( ) {}
或者
1 2 3 4 5 6 7 8 export { str, test } export default { custom : function ( ) {} }
当引入时
1 2 3 4 <script type ="module" > import * as m from './src/js/m.js' import { str } as m from './src/js/m.js' </script >
动态引入
正则 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 const str = '<a href="www.baidu.com">baidu</a>' const reg = /<a href="(.*)">(.*)<\/a>/ const result = reg.exec (str)const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/ const result = reg.exec (str)const text = result.groups .text const url = result.groups .url const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/ s
异步对象 Promise Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
创建:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 var promise = new Promise (function (resolve, reject ) { }); promise.then (onFulfilled, onRejected) promise.then (onFulfilled).catch (onRejected) getJSON ("/posts.json" ).then (function (json ) { return json.post ; }).then (function (post ) { }); var p = Promise .all ([p1,p2,p3]);var p = Promise .race ([p1,p2,p3]);var p = Promise .allSettled ([p1, p2])var jsPromise = Promise .resolve ($.ajax ('/whatever.json' ));var p = Promise .resolve ('Hello' );p.then (function (s ){ console .log (s) }); var p = Promise .reject ('出错了' );p.then (null , function (s ){ console .log (s) });
Ajax使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function ajax (URL ) { return new Promise (function (resolve, reject ) { var req = new XMLHttpRequest (); req.open ('GET' , URL , true ); req.onload = function ( ) { if (req.status === 200 ) { resolve (req.responseText ); } else { reject (new Error (req.statusText )); } }; req.onerror = function ( ) { reject (new Error (req.statusText )); }; req.send (); }); } var URL = "/try/ajax/testpromise.php" ; ajax (URL ).then (function onFulfilled (value ){ document .write ('内容是:' + value); }).catch (function onRejected (error ){ document .write ('错误:' + error); });
Async / Await async/await是基于Promise实现的,它不能用于普通的回调函数。
async可以修饰一个函数,这个函数里面可以使用await关键字。
await的语义是:必须等到await后面跟的Promise有了返回值,才能继续执行await的下一行代码。但是await是非阻塞的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 async function fn ( ){ let str = await readFile ("./a.txt" ) if (str){ let fr2 = await readFile (str) if (fr2){ console .log (fr2) } } } async function fn ( ){ return '123' } async function fn ( ){ throw new Error ('error' ) } async function fn ( ){ return new Promise ((resolve, reject ) => { reject ('error' ) }) }
TypeScript Webpack ES 6 建议使用Webpack。webpack 是一个现代 JavaScript 应用程序的静态模块打包器 (module bundler) 。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图 (dependency graph) ,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle 。
概念 webpack 主要有四个核心概念:
入口 (entry)
输出 (output)
loader
插件 (plugins)
入口 入口会指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。入口的写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const config = { entry : "./src/main.js" } const config = { app : "./src/main.js" , vendors : "./src/vendors.js" } const config = { entry : "./src/main.js" , output : { filename : "bundle.js" , path : path.resolve (__dirname, 'dist' ) } }
loader loader 让 webpack 可以去处理那些非 JavaScript 文件( webpack 自身只理解 JavaScript )。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 const config = { entry : "./src/main.js" , output : { filename : "bundle.js" , path : path.resolve (__dirname, 'dist' ) }, module : { rules : [ { test : /\.js$/ , exclude : /node_modules/ , loader : "babel-loader" , options : [ presets : ["env" ] ] } ] } }
插件 loader 被用于转换某些类型的模块,而插件则可以做更多的事情。包括打包优化、压缩、定义环境变量等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const HtmlWebpackPlugin = require ('html-webpack-plugin' );const webpack = require ('webpack' ); const config = { module : { rules : [ { test : /\.js$/ , exclude : /node_modules/ , loader : "babel-loader" } ] }, plugins : [ new HtmlWebpackPlugin ({template : './src/index.html' }) ] };
搭建应用webpack.config.js
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 const path = require ('path' ); module .exports = { mode : "development" , entry : "./src/main.js" , output : { filename : "bundle.js" , path : path.resolve (__dirname, 'dist' ) }, module : { rules : [ { test : /\.js$/ , exclude : /node_modules/ , loader : "babel-loader" , options : [ presets : ["env" ] ] } ] }, plugins : [ ... ] }
gulp gulp 是一个基于流的自动化构建工具,具有易于使用、构建快速、插件高质和易于学习的特点,常用于轻量级的工程中。
在项目根目录下创建名为 gulpfile.js 的文件:
1 2 3 4 5 6 7 8 const gulp = require ('gulp' );const uglify = require ("gulp-uglify" ); gulp.task ('default' , function ( ) { gulp.src ('./src/main.js' ) .pipe (uglify ()) .pipe (gulp.dest ('./dist' )); })
使用 安装Webpack,首先要安装node.js。
node.js 官网
1 2 3 4 5 6 7 cnpm install webpack -g mkdir apptouch app/app.jstouch app/index.html
1 document .write ("It works." );
1 2 3 4 5 6 7 8 <html > <head > <meta charset ="utf-8" > </head > <body > <script type ="text/javascript" src ="bundle.js" charset ="utf-8" > </script > </body > </html >
然后打包应用:
1 2 3 webpack app.js bundle.js webpack
配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var webpack=require ('webpack' ); module .exports = { entry : "./app.js" , output : { path : __dirname, filename : "bundle.js" }, module : { loaders : [ { test : /\.css$/ , loader : "style-loader!css-loader" } ] }, plugins :[ new webpack.BannerPlugin ('菜鸟教程 webpack 实例' ) ] };
JSX