ES6是ECMA为JavaScript制定的第6个标准版本,标准委员会决定,标准在每年6月正式发布并作为当年的正式版本,接下来的时间里就在此版本的基础上进行改动,直到下一年6月草案就自然变成新一年的版本,这样一来就无需以前的版本号,只要用年份标记即可。ECMAscript 2015
是在2015年6月
发布ES6的第一个版本。以此类推,ECMAscript 2016
是ES6的第二个版本、 ECMAscript 2017
是ES6的第三个版本。
ES6既是一个历史名词也是一个泛指,含义是5.1版本
以后的JavaScript下一代标准
,目前涵盖了ES2015
、ES2016
、ES2017
、ES2018
、ES2019
、ES2020
。
所以很多文章提到的es7,es8等,实质上都是不规范的概念,从ES1到ES6,每个标准都是花了好几年甚至十多年才制定下来,你一个ES6到ES7,ES7到ES8,才用了一年,按照这样的定义下去,那不是很快就ES20了。用正确的概念来说ES6目前涵盖了ES2015、ES2016、ES2017、ES2018、ES2019、ES2020。
另外,ES6更新的内容主要分为以下几点
表达式:声明、解构赋值
内置对象:字符串扩展、数值扩展、对象扩展、数组扩展、函数扩展、正则扩展、Symbol
、Set
、Map
、Proxy
、Reflect
语句与运算:Class
、Module
、Iterator
异步编程:Promise
、Generator
、Async
注意
const
实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。const
只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only
共享内存和原子操作:由全局对象SharedArrayBuffer
和Atomics
实现,将数据存储在一块共享内存空间中,这些数据可在JS主线程
和web-worker
线程之间共享
globalThis:作为顶层对象,指向全局环境下的this
Browser:顶层对象是window
Node:顶层对象是global
WebWorker:顶层对象是self
以上三者:通用顶层对象是globalThis
do表达式:封装块级作用域的操作,返回内部最后执行表达式的值(do{}
)
throw表达式:直接使用throw new Error()
,无需()
或{}
包括
!#命令:指定脚本执行器(写在文件首行)
字符串解构:const [a, b, c, d, e] = "hello"
数值解构:const { toString: s } = 123
布尔解构:const { toString: b } = true
对象解构
const { x, y } = { x: 1, y: 2 }
const { x, y = 2 } = { x: 1 }
const { x, y: z } = { x: 1, y: 2 }
数组解构
Iterator
接口可采用数组形式的解构赋值const [x, y] = [1, 2]
const [x, y = 2] = [1]
函数参数解构
function Func([x = 0, y = 1]) {}
function Func({ x = 0, y = 1 } = {}) {}
应用场景
[x, y] = [y, x]
const [x, y, z] = Func()
Func([1, 2])
const { name, version } = packageJson
function Func({ x = 1, y = 2 } = {}) {}
for (let [k, v] of Map) {}
const { readFile, writeFile } = require("fs")
注意
undefined
undefined
undefined
和null
无法转为对象,因此无法进行解构let x;
{x} = {x: 1};
// SyntaxError: syntax error
这段代码会报错,因为JavaScript引擎会将{x}
理解成一个代码块,从而发生语法错误。
只有不将大括号写在行首,避免JavaScript将其解释为代码块,才能解决这个问题。
\u{0xXX}
或\u{0XXX}
),有了这种表示法之后,JavaScript 共有 6 种方法可以表示一个字符。‘\z‘ === ‘z‘ // true
‘\172‘ === ‘z‘ // true
‘\x7A‘ === ‘z‘ // true
‘\u007A‘ === ‘z‘ // true
‘\u{7A}‘ === ‘z‘ // true
for-of
遍历字符串for (let codePoint of ‘foo‘) {
console.log(codePoint)
}
// "f"
// "o"
// "o"
//这个遍历器最大的优点是可以识别大于0xFFFF的码点,传统的for循环无法识别这样的码点。
let text = String.fromCodePoint(0x20BB7);
for (let i = 0; i < text.length; i++) {
console.log(text[i]);
}
// " "
// " "
for (let i of text) {
console.log(i);
}
// "??"
字符串模板:可单行可多行可插入变量的增强版字符串
标签模板:函数参数的特殊调用,需要注意的是:模板字符串中变量必须是由非变量包含着的,如果变量在开始位置或者结束位置且没有非变量包含,那么该位置就是空字符串。
var a = 5;
var b = 10;
tag`Hello ${ a + b } world ${ a * b }`;
//等同于
tag([‘Hello ‘, ‘ world ‘, ‘‘], 15, 50);
let name = "Bob";
String.raw `Hi\n${name}!`;
// "Hi\nBob!",内插表达式还可以正常运行
String.fromCodePoint(42); // "*"
String.fromCodePoint(65, 90); // "AZ"
String.fromCodePoint(0x404); // "\u0404"
codePointAt():返回字符对应码点(String.fromCodePoint()
的逆操作)
normalize():把字符的不同表示方法统一为同样形式,返回新字符串(Unicode
正规化)
repeat():把字符串重复n次,返回新字符串
matchAll():返回正则表达式在字符串的所有匹配
includes():是否存在指定字符串
startsWith():是否存在字符串头部指定字符串
endsWith():是否存在字符串尾部指定字符串
const str = ‘123‘
str.padStart(str.length + 1, ‘a‘) // => ‘a123‘
UTF-8
标准的字符串0bXX
或0BXX
)0oXX
或0OXX
)-2^53
)2^53
)NaN
e^n - 1
1 + n
的自然对数(Math.log(1 + n)
)Math.pow()
)BigInt
类型BigInt
为0
到2n-1
之间对应的值BigInt
为-2n-1
到2n-1-1
Number.parseInt()
,将一个字符串转换成指定进制的BigInt
类型let budget = 1_000_000_000_000;
budget === 10 ** 12 // true
{ prop, method() {} }
)[prop]
,不能与上同时使用)enumerable
method() {}
)getter
)和存值函数(setter
):get
/set
函数名(属性的描述对象在get
和set
上)bound
函数名anonymous
{ ...obj }
,相当于rest
/spread
参数的逆运算)Object.entries()
的逆操作)undefined
且不再往下执行)
obj?.prop、obj?.[expr]
func?.(...args)
undefined
或null
,是则使用默认值[...arr]
,相当于rest
/spread
参数的逆运算)Iterator
接口的数据结构为真正数组,返回新数组
length
的对象、Arguments
对象、NodeList
对象String
、Set结构
、Map结构
、Generator函数
undefined
(空位处理规不一,建议避免出现)function Func(x = 1, y = 2) {}
rest/spread参数(...):返回函数多余参数,以数组的形式存在,之后不能再有其他参数
严格模式:在严格条件下运行JS,如果函数参数使用默认值、解构赋值、扩展运算符,那么函数内部就不能显式设定为严格模式
箭头函数(=>):函数简写
尾调用优化:只保留内层函数的调用帧,不会发生栈溢出,相对节省内存
function f(x) { return g(x); }
catch()
中的参数可省略let obj = {
f(x, y) { return x + y; },
};
const g = obj.f(?, 3);
g(1) // 4
f(x) => x |> f
)bind
、apply
、call
调用)
bar.bind(foo) => foo::bar
bar.apply(foo, arguments) => foo::bar(...arguments)
match()
、replace()
、search()
、split()
内部调用转为调用RegExp
实例对应的RegExp.prototype[Symbol.方法]
Unicode
模式修饰符,正确处理大于\uFFFF
的Unicode
字符g修饰符
作用类似)u修饰符
y修饰符
dotAll模式
修饰符,使.匹配任意单个字符(dotAll模式
)s修饰符
x
只有在y
后才匹配x
只有不在y
后才匹配Unicode
某种属性的所有字符
\p{PropRule}
\P{PropRule}
\p{...}
和\P{...}
只对Unicode
字符有效,使用时需加上u修饰符
?<GroupName>
)独一无二的值, symbol
类似于数组的数据结构,成员值都是唯一且没有重复的值, set
类似于对象的数据结构,成员键是任何类型的值, map
修改某些操作的默认行为,proxy
const proxy = new Proxy(target, handler)
保持Object方法
的默认行为。reflect
设计目的
对一类具有共同特征的事物的抽象(实质是基于原型的继承的语法糖), class
export default Person
import Person from "person"
export命令
和import命令
结合在一起写成一行,变量实质没有被导入当前模块,相当于对外转发接口,导致当前模块无法直接使用其导入变量export { default } from "person"
其他模块方案
//CommonJS
// a.js
module.exports = {
a: 1
}
// or
exports.a = 1
// b.js
var module = require(‘./a.js‘)
module.a // -> log 1
// AMD
define([‘./a‘, ‘./b‘], function(a, b) {
// 加载模块完毕可以使用
a.do()
b.do()
})
// CMD
define(function(require, exports, module) {
// 加载模块
// 可以把 require 写在函数体的任意地方实现延迟加载
var a = require(‘./a‘)
a.doSomething()
})
//UMD
(function (root, factory) {
if (typeof define === ‘function‘ && define.amd) {
//AMD
define([‘jquery‘], factory);
} else if (typeof exports === ‘object‘) {
//Node, CommonJS之类的
module.exports = factory(require(‘jquery‘));
} else {
//浏览器全局变量(root 即 window)
root.returnExports = factory(root.jQuery);
}
}(this, function ($) {
//方法
function myFunc(){};
//暴露公共方法
return myFunc;
}));
为各种不同的数据结构提供统一的访问机制, 主要使用for-of
进行遍历, iterator
包含异步操作结果的对象, promise
封装多个内部状态的异步编程解决方案
function Wrapper(func) {
return function(...args) {
const generator = func(...args);
generator.next();
return generator;
}
}
const print = Wrapper(function*() {
console.log(`First Input: ${yield}`);
return "done";
});
print().next("hello");
注意
next()
,指针就从函数头部或上次停下的位置开始执行,直到遇到下一个yield命令
或return语句
为止yield命令
,但会变成单纯的暂缓执行函数(还是需要next()
触发)yield命令
是暂停执行的标记,next()
是恢复执行的操作yield命令
用在另一个表达式中必须放在圆括号里yield命令
用作函数参数或放在赋值表达式的右边,可不加圆括号yield命令
本身没有返回值,可认为是返回undefined
yield命令
表达式为惰性求值,等next()
执行到此才求值Symbol.iterator
是此对象本身next()
从外部向内部注入不同的值,从而调整函数行为next()
用来启动遍历器对象,后续才可传递参数next()
时就能输入值,可在函数外面再包一层next()
返回对象的done
为true
,for-of
遍历会中止且不包含该返回对象try-finally
且正在执行try
,那么return()
会导致立刻进入finally
,执行完finally
以后整个函数才会结束throw()
抛错要被内部捕获,前提是必须至少执行过一次next()
throw()
被捕获以后,会附带执行下一条yield命令
throw()
抛错只可能抛出在函数外部提供沙箱功能
,允许隔离代码,防止被隔离的代码拿到全局对象
new Realm().global
原文:https://www.cnblogs.com/wangxi01/p/12757767.html