ES6已经出现很长时间了,现在系统一下知识点,查漏补缺。
变量
let
let
声明的变量只在其所在的代码块中起作用。
- 使用
let
声明变量之前。该变量是不可用的 - 暂时性死区
let
不允许在同一个作用域内重复声明同一个变量。
- 在块级作用域内函数声明类似于
let
,在块级作用域之外不可引用。
const
const
声明一个只读变量,一旦声明常量不可变。
const
实际上保证的是变量指向的那个内存地址不得改动,引用类内部属性还是可变的。
获取顶层对象
1 2 3 4 5 6
|
function getGlobal(){ if ( typeof self !== 'undefined' ) { return self; } if ( typeof window !== 'undefined' ) { return window; } if ( typeof global !== 'undefined' ) { return global; } throw new Error("unable to locate global object !!! "); }
|
结构赋值 - 按照一定的模式从数组或者对象中提取值,然后对变量进行赋值。
字符串
Unicode(utf-8/utf-16)字符表示方法:\u{0061}
\u{20BB7}
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 44 45 46 47 48 49 50
|
var buf = "𠮷a"; // codePointAt() 能够正确处理 utf-16 字符。 buf.codePointAt(0).toString(16); // 20bb7 buf.codePointAt(1).toString(16); // 61 // fromCodePoint() 通过码点获取正确 utf-16 字符。 String.fromCodePoint(0x20bb7); // 𠮷 // 字符串遍历器 for...of 有效识别 utf-16 for(let c of buf){ console.log(c); // 𠮷 、 a } // at() 返回给定位置的字符 'abc'.at(0); // a // normalize() 正规化 - 针对某些语言的合成词 // includes() 是否包含 // startsWith() 是否开头 // endsWith() 是否结尾 // repeat() 重复 // padStart() 在开始补全 'x'.padStart(5, 'yz'); // yzyzx 'x'.padStart(4, 'yz'); // yzyx // padEnd() 在结尾补全 'x'.padEnd(5, 'yz'); // xyzyz 'x'.padEnd(4, 'yz'); // xyzy // 模板字符串 var template = `this is an template String ${buf}`; // 模板编译函数 function compile(template){ let evalExpr = /<%=(.+?)%>/g; let expr = /<%=([\\s\\S]+?)%>/g; template = template .replace(evalExpr, '`); \\n echo( $1 ); \n echo(`') .replace(expr, '`); \n $1 \\n echo(`'); template = 'echo(`'+ template +'`);'; var script = `(function parse(data){ let output = ""; function echo(html){ output += html; }
${ template }
return output; })`; return script; } // 使用模板编译 let parse = eval(compile(template)); let html = parse(data); // raw() 模板字符串处理函数 用于转义模板字符串中的内容
|
正则
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
// 创建方式 new RegExp('xyz','i'); new RegExp(/xyz/i); /xyz/i; new RegExp(/xyz/ig,"i"); // ig 会被 i 覆盖 仅支持es6 // match() // replace() // search() // split() // u 修饰符 处理 utf-16 // y 修饰符 下一次匹配必须在开始位置 // 正则的 sticky 属性 与y修饰符相匹配 // 正则的 flags 属性 返回正则的修饰符 // s 修饰符 .号不匹配行终止符 需要加此修饰符进行匹配 dotAll模式
|
- 先行断言:x只有在y前面才能匹配
/x(?=y)/
- 先行否定断言: x只有不在y前面才能匹配
/x(?!y)/
- 后行断言:x只有在y后边才能匹配
/(?<=y)x/
- 后行否定断言:x只有不在y后面才能匹配
/(?<!y)x/
匹配Unicode \p{...}
或者 \P{...}
具名组匹配 ?<name>
1 2 3
|
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; const matchObj = RE_DATE.exec('1999-12-31'); const year = matchObj.groups.year;
|
数值
二进制前缀 0b
八进制前缀 0o
十六进制前缀 0x
Number
对象
1 2 3 4 5 6 7
|
Number.isFinite() // 检查数值是否是有限的 Number.isNaN() // 检查数值是否为 NaN Number.parseInt() // 转换 int Number.parseFloat() // 转换 float Number.isInteger() // 判断是否为整数 Number.EPSILON // 极小的常量 浮点的误差范围 Number.isSafeInteger() // 整数是否在安全范围内
|
Math
对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
Math.trunc() // 去除小数部分 Math.sign() // 判断是正数 负数 还是 零 返回:1、-1、0、-0、NaN Math.cbrt() // 计算一个数的立方根 Math.clz32() // 返回一个数的32位无符号整数形式有多少个前导0 Math.imul() // 返回两个数的乘积 保证溢出后的低位精度 Math.fround() // 返回单精度浮点数 Math.hypot() // 返回所有参数的平方和的平方根 // 对数 Math.expm1() // 返回 e^x - 1 即 Math.exp(x) - 1 Math.log1p() // 返回 ln(1 + x) 即 Math.log(1 + x) 如果x小于-1返回NaN Math.log10() // 返回以10为底的x的对数 如果x<0则返回NaN Math.log2() // 返回以2为底的x的对数 如果x<0则返回NaN // 双曲函数 Math.sinh() // 双曲正弦 Math.cosh() // 双曲余弦 Math.tanh() // 双曲正切 Math.asinh() // 反双曲正选 Math.acosh() // 反双曲余弦 Math.atanh() // 反双曲正切
Math.signbit() // 符号位是否已经设置 // 指数运算符 **
// Integer数值类型需要以n结尾
|
函数
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
function log(x,y='World'){ console.log(x,y); } function log({x = 'Hello',y = 'World'}={}){ console.log(x,y); } function log({x,y} = {x:'Hello',y:'World'}){ console.log(x,y); }
// 函数的length属性,代表返回参数个数
// 参数不存在就抛出异常 function throwMissing(param){ throw new Error("Missing parameter " + param ); } function log(x = throwMissing('x'),y='World'){ console.log(x,y); }
// 扩展运算符 ...y 必须在末尾 // 数组与参数的逆运算 function log(x, ...y){}
// 箭头函数 => let sum = (x, y) => x + y ;
// 函数绑定运算符 :: 左边的对象绑定到右边的函数上,使函数中this指向左边的对象。
// 尾调用优化 function f(x){ return g(x); }
// 蹦床函数 尾递归优化 将递归转化为循环 function tco(f){ var value; var active = false; var accumulated = [];
return function accumulator(){ accumulated.push(arguments)l if(!active){ active = true; while(accumulated.length){ value = f.apply(this, accumulated.shift()); } active = false; return value; } }; }
var sum = tco(function(x,y){ if(y>0){ return sum(x + 1,y - 1); }else{ return x; } });
sum(1,100000); // 100001
// 尾逗号 function abc(a,b,c,){
}
|
数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
// 扩展运算符 ... // 合并数组 arr = [1] arr2 = [2,3] arr3 = [4,5] [...arr, ...arr2, ...arr3] // [1,2,3,4,5] [first, ...rest] = [1,2,3,4,5] // first = 1 ;rest = [2,3,4,5] Array.from() // 转化为真正数组 Array.of() // 将一组值 转化为数组 arr.copyWithin() // 当前数组内的指定位置复制到其他位置 arr.find() // 返回符合条件的数组 arr.findIndex() // 返回符合条件的数组成员的位置 arr.fill() // 使用给定的值填充一个数组 arr.entries() // 键值对遍历用 for...of arr.keys() // 键遍历用 for...of arr.values() // 值遍历用 for...of arr.includes() // 包含
// 数组空位 会明确的作为undefined处理
|
对象
1 2 3 4 5 6 7 8
|
Object.is() // 判断两个值相等 Object.assign(target, ...sources) // 将源对象的可枚举属性复制到目标对象 function clone(origin){ let originProto = Object.getPrototypeOf(origin); return Object.assign(Object.create(originProto),origin); } Object.getOwnPropertyDescriptor(); // 属性描述 // for ... in/Object.keys/JSON.stringify/Object.assign 会忽略枚举属性为false的值
|
对象遍历
- for...in 遍历自身和继承的可枚举属性(不含Symbol属性)
- Object.keys(obj) 遍历自身(不含继承)的可枚举属性(不含Symbol属性)
- Object.getOwnPropertyNames(obj) 遍历自身的所有属性(不含Symbol属性)
- Object.getOwnPropertySymbols(obj) 遍历自身所有Symbol属性
- Reflect.ownKeys(obj) 遍历自身所有属性
1 2 3 4 5 6 7 8 9 10 11 12
|
// __proto__ 属性 - 内部属性,不建议使用 Object.setPrototypeOf(object, prototype) // 写操作 Object.getPrototypeOf() // 读操作 Object.keys(object) // 遍历自身(不含继承)的可枚举属性(不含Symbol属性) Object.values(object) // 参数对象自身的(不含继承的)所有可遍历属性的键值 Object.entries(object) // 参数对象自身的(不含继承的)所有可遍历属性的键值数组 Object.getOwnPropertyDescriptor(object, 'propName') // 返回某个对象属性的描述对象 Object.getOwnPropertyDescriptors(object) // 同上
// Null传导运算符 var a = b?.c?.d?.e; // b c d 有一个是 undefined 或者 null 都会直接返回
|
Symbol 独一无二的值
七种数据类型:Undefined
、Null
、 Boolean
、 String
、 Number
、 Object
、 Symbol
使用方式:
1 2 3 4 5
|
let s = Symbol(); // 接受参数作为描述 在控制台显示区分 let s = Symbol('abc'); // 如果参数是一个对象 就会调用对象的toString方法 // 每次生成的Symbol都不相等
|
Symbol
作为属性名,可以用于构建枚举量或者内部方法。
1 2
|
Symbol.for() // 检索已经存在的量 不存在则新建 Symbol.keyFor() // 返回Symbol的key值
|
对象的11个内置Symbol
值
- Symbol.hasInstance
- Symbol.isConcatSpreadable
- Symbol.species
- Symbol.match
- Symbol.replace
- Symbol.search
- Symbol.split
- Symbol.iterator
- Symbol.toPrimitive
- Symbol.toStringTag
- Symbol.unscopables
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
// #1 class MyClass{ [Symbol.hasInstance](p){ return p instanceof Array; } } [1, 2, 3] instanceof new MyClass(); // true
// #2 let obj = {length:2, 0:'c', 1:'d'}; ['a','b'].concat(obj,'e'); // a b obj e
obj[Symbol.isConcatSpreadable] = true; // 需要手动设置 ['a','b'].concat(obj,'e'); // a b c d e
// #3
|
Set Map
- Set - add delete has clear size
- WeakSet - 成员只能是对象
- Map - size set get has delete clear
- WeakMap - 仅接受对象作为键名 没有size属性
- WeakMap 很适合实现listener 和 部署私有属性
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
|
// Map转对象 function strMapToObj(strMap){ let obj = Object.create(null); for(let [k,v] of strMap){ obj[k] = v; } return obj; } // 对象转Map function objToStrMap(obj){ let strMap = new Map(); for(let k of Object.keys(objs)){ strMap.set(k,obj[k]); } return strMap; } // Map转JSON function strMapToJson(strMap){ return JSON.stringify(strMapToObj(strMap)); } function mapToArrayJson(strMap){ return JSON.stringify([...strMap]); } // JSON转Map function jsonToStrMap(jsonStr){ return objToStrMap(JSON.parse(jsonStr)); } function jsonToMap(sonStr){ return new Map(JSON.parse(jsonStr)); }
|
Proxy 修改某些操作的默认行为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
// 实例方法 get() set() apply() has() construct() deleteProperty() defineProperty() getOwnPropertyDescriptor() getPrototypeOf() isExtensible() ownKeys() preventExtensions() setPrototypeOf() Proxy.revocable()
|
Reflect 类似 Proxy
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
// 13个静态方法 Reflect.apply Reflect.construct Reflect.get Reflect.set Reflect.defineProperty Reflect.deleteProperty Reflect.has Reflect.ownKeys Reflect.isExtensible Reflect.preventExtensions Reflect.getOwnPropertyDescriptor Reflect.getPrototypeOf Reflect.setPrototypeOf
|
Promise
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
|
// 使用实例 var promise = new Promise(function(resolve,reject){ // ... some code
if(/*异步操作成功*/){ resolve(value); }else{ reject(error); } }); promise.then(function(value){ // 成功 },function(error){ // 失败 }).catch(console.error); // 推迟执行 function timeout(ms){ return new Promise((resolve,reject) => { setTimeout(resolve, ms, 'done'); }); } timeout(100).then((value) => console.log(value)); // 异步加载图片 function loadImageAsync(url){ return new Promise((res,rej)=>{ let image = new Image(); image.onload = function(){ res(image); }; image.onerror = function(){ rej(new Error("Could not load image at " + url)); }; image.src = url ; }); } // Promise 实现 ajax function getJSon(url){ return new Promise((res, rej)=>{ let client = new XMLHttpRequest(); client.open("GET",url); client.onreadystatechange = handler; client.responseType = "json"; client.setRequestHeader("Accept", "application/json"); client.send(); function handler(){ if(this.readyState !== 4){ return ; } if(this.status === 200){ res(this.response); }else{ rej(new Error(this.statusText)); } } }); } // Promise.all 全部状态改变才改变 var a = Promise.all([new Promise(),new Peomise()]); // Promise.race() 有一个改变就返回 var a = Promise.race([new Promise(),new Peomise()]); // Promise.resolve() 将普通方法转换为Promise方法 // Promise.reject()
// done() Promise.prototype.done = function(onFulfilled, onRejected){ this.then(onFulfilled, onRejected).catch(function(reason){ setTimeout(function(){throw reason;},0); }); } // finally() Promise.prototype.finally = function(callback){ let P = this.constructor; return this.then( value => P.resolve(callback()).then(() => value), reason => P.resolve(callback()).then(() => { throw reason}) ); } // Promise.try() catch 方法仅捕捉异步错误 所以需要try捕捉更多问题
|
Iterator 和 for ... of
Genertor函数 异步编程解决方案
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
|
function* gen(){ yield "hello"; yield "world"; yield "ending"; } var g = gen(); g.next(); // { value : "hello", done: false} g.next(); // ...
// Generator.prototype.return()
function* clock(){ while(true){ console.log("tick!"); yield; console.log("tock!"); yield; } } // 协程
// Thunk函数 自动执行Gen函数 //es5 var Thunk = function(fn){ return function(){ var args = Array.prototype.slice.call(arguments); return function (callback){ args.push(callback); return fn.apply(this, args); }; }; }; //es6 const Thunk = function(fn){ return function(...args){ return function(callback){ return fn.call(this, ...args,callback); }; }; };
// Thunkify 模块(建议生产环境用这个) // co 模块 自动执行gen程序 ***
|
async 改进 gen函数
1 2 3 4 5 6
|
// 实例 async function funcName(){ var f1 = await readFile(); // ... } funName();
|
Class
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
|
class Point{ constructor(x,y){ this.x = x; this.y = y; this.__a = 123; console.log('point run'); } set prop(str){ console.log(str); } get prop(){ return "123"; } toString (){ return "hello"; } static say(){ console.log(this.__a); } } Point.prop = 1;// 静态属性
class ColorPoint extends Point{ constructor(){ super(1,1); console.log('color point run'); } }
|
修饰器
Module语法
1 2 3 4 5
|
import {stat, exist, readFile} from 'fs'; var a = 1; var b = 2; export const A = 1; // 输出常量 export {a as c, b};
|