ES5 和 ES6 区别
ES5 和 ES6 分别实现函数默认参数
1 2 3 4 5 6 7 8 9 10 11 12
| function test(param) { param = param || "default param"; ... } function test(param = "default param") { ... }
|
ES5 和 ES6 分别实现字符串模板
1 2 3 4 5 6 7
| var compiled = _.template("hello: <%= name %>"); compiled({name: "world"}); var name = "world"; var string = `hello ${name}`;
|
ES6 特性
let 和 const
let 声明的变量只在声明的块作用域中有效
1 2 3 4 5 6 7 8
| function test(){ for (let i = 1; i < 3; i++) { console.log(i); } console.log(i); } test();
|
let 声明的变量不能被 let 重复声明
1 2 3 4 5 6
| function test(){ let a = 1; let a = 2; } test();
|
const 声明的变量在声明之后无法修改其赋值
1 2 3 4 5 6 7
| function test(){ const PI = 3.1415926535; PI = 8; console.log(PI); } test();
|
const 声明的变量必须在声明时候赋值
1 2 3 4 5 6 7
| function test(){ const PI; PI = 3.1415926535; console.log(PI); } test();
|
解构赋值
数组解构赋值
example1
1 2 3
| let a, b, c; [a, b, c] = [1, 2, 3]; console.log(a, b, c);
|
example2
1 2 3
| let a, b, c; [a, b, ...c] = [1, 2, 3, 4, 5]; console.log(a, b, c);
|
example3
1 2 3
| let a, b, c, d; [a, b, c = 3, d] = [1, 2]; console.log(a, b, c, d);
|
对象解构赋值
1 2 3
| let a, b; ({a,b} = {a:1, b:2}); console.log(a, b);
|
使用场景
交换赋值
1 2 3 4 5 6 7 8 9 10 11 12
| var a = 6, b = 9, tmp; tmp = a ; a = b; b = tmp; console.log(a, b); let a = 6; let b = 9; [a, b] = [b, a]; console.log(a, b);
|
获取函数返回值 1
1 2 3 4 5 6 7
| function test(){ return [1, 2]; } let a, b; [a, b] = test(); console.log(a, b);
|
获取函数返回值 2
1 2 3 4 5 6 7
| function test(){ return [1, 2, 3, 4, 5]; } let a, b, c; [a,,,b] = f(); console.log(a, b);
|
获取函数返回值 3
1 2 3 4 5 6 7
| function test(){ return [1, 2, 3, 4, 5]; } let a, b, c; [a,,...b] = test(); console.log(a,b);
|
获取对象返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| { let data = { title: 'abc', test: [ { title: 'efg', description: 'Hello World' } ] }; let {title: esTitle, test: [{title: tsTitle, description: helloWorld}]} = data; console.log(esTitle, tsTitle, helloWorld); }
|
字符转扩展
Unicode 表示法
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
| { console.log('a', `\u0061`); console.log('s', `\u20BB7`); console.log('s', `\u{20BB7}`); } { let s = '𠮷'; console.log('length', s.length); console.log('0', s.charAt(0)); console.log('1', s.charAt(1)); console.log('at0', s.charCodeAt(0)); console.log('at1', s.charCodeAt(1)) let w = '𠮷A'; console.log('length', w.length); console.log('code0', w.codePointAt(0)); console.log('code0', w.codePointAt(0).toString(16)); console.log('code1', w.codePointAt(1)); console.log('code2', w.codePointAt(2)); } { console.log(String.fromCharCode("0x20bb7")); console.log(String.fromCodePoint("0x20bb7")); }
|
遍历接口
1 2 3 4 5 6 7 8 9 10 11 12
| { var string = '\u{20bb7}abc'; for(let i=0; i < string.length; i++){ console.log('es5', string[i]); } for(let code of string){ console.log('es6', code); } }
|
新增方法
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
| { let string = "string"; console.log("inculdes", string.includes("r")); console.log("start", string.startsWith("str")); console.log("start", string.endsWith("ng")); let a = "abc"; console.log(a.repeat(2)); let name = "Luis Edware"; let info = "Hello World"; let temp = `I am ${name}, ${info}`; console.log(temp); let user = { name: "luis", info: "hello world" }; function test(s, v1, v2){ console.log(s, v1, v2); } test`i am ${user.name},${user.info}`; console.log(String.raw`Hi\n${1+2}`); console.log(`Hi\n${1+2}`); }
|
数值扩展
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
| { console.log(0B111110111111); console.log(0O767); console.log('15', Number.isFinite(15)); console.log('NaN', Number.isNaN(NaN)) console.log('Integer 25', Number.isInteger(25)); console.log('Integer 25.0', Number.isInteger(25.0)); console.log('String 25', Number.isInteger("25")); console.log(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER); console.log('10', Number.isSafeInteger(10)); console.log('90071992547409919', Number.isSafeInteger(90071992547409919)); console.log(4.1, Math.trunc(4.1)); console.log(4.9, Math.trunc(4.9)); console.log(-5, Math.sign(-5)); console.log(1, Math.sign(1)); console.log('string', Math.sign('string')); console.log(0, Math.sign(0)); console.log('-1', Math.cbrt(-1)); console.log('8', Math.cbrt(8)); }
|
数组扩展
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
| { let arr = Array.of(1, "Hello", 2, "World"); console.log(arr); let empty = Array.of(); console.log(empty); let p = document.querySelectorAll('p'); let pArray = Array.from(p); pArray.forEach(function(item){ console.log(item.textContent); }); let numberArr = Array.from([1, 3, 5], function (item) { return item*2; }); console.log(numberArr); for (let index of ['1', 'c', 'ks'].keys()) { console.log('key', index); } for (let [index, value] of ['1', 'c', 'ks'].entries()) { console.log('key', index); console.log('value', value); } console.log([1, 2, 3, 4, 5].copyWithin(0, 3, 4)); console.log([1, 2, 3, 4, 5, 6].find(function(item){return item > 3;})); console.log([1, 2, 3, 4, 5, 6].findIndex(function(item){return item > 3;})); console.log([1, 2, NaN].includes(1)); }
|
函数扩展
参数默认值
1 2 3 4 5 6 7 8
| { function test(x, y = 'world'){ console.log('默认值', x, y); } test('Hello'); test('Hello', 'Luis Edware') }
|
rest 参数
1 2 3 4 5 6 7 8 9
| { function test(...arg){ for (let v of arg) { console.log('rest', v); } } test(1, 2, 3, 4, 'a'); }
|
扩展运算符
1 2 3 4 5
| { console.log(...[1, 2, 4]); console.log('a',...[1, 2, 4]); }
|
箭头函数
1 2 3 4 5 6 7 8 9
| { let arrow = v => v*2; console.log('arrow', arrow(3)); let arrow2 = () => 5; console.log('arrow2', arrow2()); }
|
尾调用
1 2 3 4 5 6 7 8 9 10
| { function tail(x){ console.log('tail', x); } function fx(x){ return tail(x); } fx(123); }
|
对象扩展
简洁表示法
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
| { var o = 1; var k = 2; var es5 = { o: o, k: k } let es6 = { o, k } console.log(es5, es6); var es5Method = { hello: function(){ console.log('hello'); } } let es6Method = { hello(){ console.log('world'); } } console.log(es5Method, es6Method); }
|
属性表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| { let a = 'b'; let es5Object = { a: 'c', b: 'c' }; function test(){ return 'c'; } let es6Object = { [a]: 'c', [test()]: 'd' }; console.log(es5Object, es6Object); }
|
扩展运算符
1 2 3 4 5 6 7 8 9
| { let {a, b, ...c} = { a: 'test', b: 'kill', c: 'dddd', d: 'ffff' } console.log(a, b, c) }
|
Object 新增方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { console.log('字符串', Object.is('abc', 'abc'), 'abc' === 'abc'); console.log('数组', Object.is([], []), [] === []); console.log('拷贝', Object.assign({a: 'a'}, {b: 'b'})); let test = {k: 123, o: 456}; for (let [key, value] of Object.entries(test)) { console.log([key, value]); } }
|
Symbol
Symbol 的概念
Symbol 是一种基本数据类型
Symbol 的作用
Symbol() 函数会返回 Symbol 值,每个值都是唯一的。一个 symbol 值能作为对象属性的标识符。
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
| { let a1 = Symbol(); let a2 = Symbol(); console.log(a1 === a2); let a3 = Symbol('foo'); let a4 = Symbol('foo'); console.log(a3 === a4); } { let a1 = Symbol.for('abc'); let obj = { [a1]: '123', 'abc': 345, 'c': 456 } console.log(obj); for (let [key, value] of Object.entries(obj)) { console.log(key, value); } Object.getOwnPropertySymbols(obj).forEach(function(item){ console.log(obj[item]); }) Reflect.ownKeys(obj).forEach(function(item){ console.log('ownkeys', item, obj[item]); }) }
|
数据结构
Set
Set 对象是值的集合,你可以按照插入的顺序迭代它的元素。 Set中的元素只会出现一次,即 Set 中的元素是唯一的。
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
| { let list = new Set(); list.add(1); list.add(3); list.add(5); list.add(7); console.log('size', list.size); console.log('length', list.length); } { let arr = [1, 2, 3, 4, 5, 1, 2]; let list = new Set(arr); console.log(list); } { let arr = ['add', 'delete', 'clear', 'has']; let list = new Set(arr); console.log('has', list.has('has')); console.log('delete', list.delete('add'), list); list.clear() console.log('clear', list); } { let arr = ['add', 'delete', 'clear', 'has']; let list = new Set(arr); for (let key of list.keys()) { console.log('key', key); } for (let value of list.values()) { console.log('value', value); } for (let item of list) { console.log('item', item); } for (let [key, value] of list.entries()) { console.log('entries', key, value); } list.forEach(function(item){ console.log(item); }); }
|
WeakSet
WeakSet 和 Set 的区别:WeakSet 只能存储对象类型的数据。WeakSet 存储对象数据时是基于弱引用,不会检测对象数据是否被垃圾回收。WeakSet 类型没有 clear() 方法,WeakSet 不能遍历。
Map
new Map([iterable]),Iterable 可以是一个数组或者其他 iterable 对象,其元素或为键值对,或为两个元素的数组。 每个键值对都会添加到新的 Map。null 会被当做 undefined。
1 2 3 4 5 6 7 8 9 10 11
| { let map = new Map(); let arr = ['123']; map.set(arr, 456); console.log(map, map.get(arr)); } { let map = new Map([['a',123],['b',456]]); console.log('map args', map); console.log('size', map.size) }
|
WeakMap
- 只能存储对象类型数据
- 没有 clear() 方法
- 不能遍历
Map 与 Array 的对比
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
| { let map = new Map(); let arr = []; map.set('t', 1); arr.push({t: 1}); console.info('map-array', map, arr); let map_exist = map.has('t'); let arr_exist = arr.find(item => item.t); console.info('map-array', map_exist, arr_exist); map.set('t', 2); arr.forEach(item => item.t ? item.t = 2 : ''); console.info('map-array', map, arr); map.delete('t'); let index = arr.findIndex(item => item.t); arr.splice(index, 1); console.info('map-array', map, arr); }
|
Set 与 Array 的对比
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
| { let set = new Set(); let arr = []; obj = {t:1}; set.add(obj); arr.push(obj); console.log('set-array', set, arr); let setExist = set.has(obj); let arrExist = arr.find(item => item.t); console.log('set-array', setExist, arrExist); set.forEach(item => item.t ? item.t = 2 : ''); arr.forEach(item => item.t ? item.t = 2 : ''); console.log('set-array', set, arr); set.forEach(item => item.t ? set.delete(obj) : ''); let index = arr.findIndex(item => item.t); arr.splice(index, 1); console.info('set-array', set, arr); }
|
Map、Set 与 Object 对比
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
| { let item = {t:1}; let map = new Map(); let set = new Set(); let obj = {}; map.set('t', 1); set.add(item); obj['t'] = 1; console.log('map-set-obj', map, set, obj); console.info({ mapExist: map.has('t'), setExist: set.has(item), objExist: 't' in obj }); map.set('t', 2); item.t = 2; obj['t'] = 2; console.info('map-set-obj-modify', map, set, obj); map.delete('t'); set.delete(item); delete obj['t']; console.info('map-set-obj-delete', map, set, obj); }
|
以后使用数据结构时,优先考虑 Set 和 Map 数据结构,然后才是 Array 和 Object 数据结构
Proxy 和 Reflect
Proxy 概念、适用场景
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
| { let obj = { time: '2017-03-11', name: 'net', _r: 123 } let monitor = new Proxy(obj, { get(target, key){ if (key === 'time') { return target[key].replace('2017', '2888'); } }, set(target, key, value){ if (key === 'name') { return target[key] = value; }else{ return target[key]; } }, has(target, key){ if (key === 'name') { return target[key] }else{ return false; } }, deleteProperty(target, key){ if (key.indexOf('_') > -1) { delete target[key]; return true; }else{ return target[key]; } }, ownKeys(target){ return Object.keys(target).filter(item => item != 'time'); } }); console.log(monitor.time); console.log(monitor.name = "Hello World"); console.log(monitor._r = "_r", obj); console.log('time' in monitor, 'name' in monitor); console.log(delete monitor['_r']); console.log(delete monitor['name'], monitor); console.log(Object.keys(monitor)); }
|
Reflect 概念、适用场景
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
| { let obj = { time: '2017-03-11', name: 'net', _r: 123 } console.log("Reflect get", Reflect.get(obj, 'time')); Reflect.set(obj, 'name', 'MuKeWang'); console.log(obj); console.log(Reflect.has(obj, 'name')); } { function validator(target, validators){ return new Proxy(target, { _validators: validators, set(target, key, value, proxy){ if (target.hasOwnProperty(key)) { let va = this._validators[key]; console.log(va); if (!!va(value)) { return Reflect.set(target, key, value, proxy) }else{ throw Error(`不能设置 ${key} 到 ${value}`); } }else { throw Error(`${key} 不存在`); } } }); } const personValidators = { name(val){ return typeof val === 'string'; }, age(val){ return typeof val === 'number' && val > 18; } } class Person{ constructor(name, age){ this.name = name; this.age = age; return validator(this, personValidators); } } const person = new Person('LuisEdware', 12); console.log(person); console.log(person.age = 48); }
|
类
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
| { class Parent{ constructor(name = "LuisEdware"){ this.name = name; } } let parent = new Parent('HelloWorld'); console.log(parent); class Child extends Parent{ constructor(name){ super(name); this.type = 'child'; } } let child = new Child(); console.log(child); } { class Parent{ constructor(name = 'Luis'){ this.name = name; } get firstName(){ return "Luis"; } get fullName(){ return this.name + 'Edware'; } set firstName(value){ return this.name = value; } } parent = new Parent(); console.log(parent.firstName = "I Love You,"); console.log(parent.fullName); } { class Parent{ constructor(name = 'Luis'){ this.name = name; } static tell(){ console.log('Do you like what do you see?'); } } Parent.type = "static Propertory"; Parent.tell(); console.log('静态属性', Parent.type); }
|
Promise
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
| { let ajax = function(callback){ console.log('执行1'); setTimeout(function(){ callback && callback.call(); }, 2000); } ajax(function(){ console.log('TimeOut 2'); }); } { let ajax = function(){ console.log('执行2'); return new Promise(function(resolve, reject){ setTimeout(function () { resolve(); }, 4000) }) } ajax().then(function(){ console.log("TimeOut 4"); },function(){ }); } { let ajax = function(){ console.log('执行3'); return new Promise(function(resolve, reject){ setTimeout(function () { resolve(); }, 1000) }) } ajax().then(function(){ console.log("执行 3-1"); return new Promise(function(resolve, reject){ setTimeout(function () { resolve(); }, 1000) }); }).then(function(){ console.log("执行 3-2"); }); } { let ajax = function(num){ console.log('执行4'); return new Promise(function(resolve, reject){ if (num > 5) { resolve(); }else{ throw new Error("出现错误"); } }); } ajax(6).then(function(){ console.log('log', 6); }).catch(function(error){ console.log('catch', error); }); ajax(3).then(function(){ console.log('log', 3); }).catch(function(error){ console.log('catch', error); }); } { function loadImg(src){ return new Promise((resolve, reject) => { let img = document.createElement('img'); img.src = src; img.onload = function(){ resolve(img); } img.onerror = function(){ reject(err); } }) } function showImgs(imgs){ imgs.forEach(function(img){ document.body.appendChild(img); }) } Promise.all([ loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1514996206326&di=167c5eb9be5db7f9dd33714cfd7bb271&imgtype=0&src=http%3A%2F%2Fimg.shouyoutan.com%2FUploads-s%2Fnews%2F2017-08-03%2F5982c65433748.jpg'), loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1514996240993&di=8f5bbd56e43773a3bfe6f7c28c88d219&imgtype=jpg&src=http%3A%2F%2Fimg4.imgtn.bdimg.com%2Fit%2Fu%3D1635656209%2C4021449300%26fm%3D214%26gp%3D0.jpg'), loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1514996213584&di=96bc51499c4786b86a4f158111dd8014&imgtype=0&src=http%3A%2F%2Fxs.dmzj.com%2Fimg%2F127%2F19%2F4409de1973e9ee2f2ddec617dcfebb6d.jpg') ]).then(showImgs); } { function loadImg(src){ return new Promise((resolve, reject) => { let img = document.createElement('img'); img.src = src; img.onload = function(){ resolve(img); } img.onerror = function(){ reject(err); } }) } function showImgs(img){ let p = document.createElement('p'); p.appendChild(img); document.body.appendChild(p); } Promise.race([ loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1514996206326&di=167c5eb9be5db7f9dd33714cfd7bb271&imgtype=0&src=http%3A%2F%2Fimg.shouyoutan.com%2FUploads-s%2Fnews%2F2017-08-03%2F5982c65433748.jpg'), loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1514996240993&di=8f5bbd56e43773a3bfe6f7c28c88d219&imgtype=jpg&src=http%3A%2F%2Fimg4.imgtn.bdimg.com%2Fit%2Fu%3D1635656209%2C4021449300%26fm%3D214%26gp%3D0.jpg'), loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1514996213584&di=96bc51499c4786b86a4f158111dd8014&imgtype=0&src=http%3A%2F%2Fxs.dmzj.com%2Fimg%2F127%2F19%2F4409de1973e9ee2f2ddec617dcfebb6d.jpg') ]).then(showImgs); }
|
模块化
- export 语句用于在创建 JavaScript 模块时,从模块中导出函数、对象或原始值,以便其他程序可以通过 import 语句使用它们。
- import 语句用于导入由另一个模块导出的绑定。
export
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
| export let a = 123; export function test(){ console.log('test'); } export class Hello{ test(){ console.log('class'); } } let a = 123; let test = function(){ console.log('test'); } class Hello{ test(){ console.log('class'); } } export default { a, test, Hello }
|
import
1 2 3 4 5
| import {a, test, Hello} from 'file.js'; import * as all from 'file.js'; import Luis from 'file'.js
|