import { Agent } from "http";
// es6新增块作用域 声明变量const和 let作用于块
// const声明的常量不可以重新赋值,但是对象可以发生改变
function test() {
const PI = 3.14;
const k = {
a: 1
}
k.b = 3;
// 输出为object:{a:1 ,b:2}
}
// 解构赋值 左右结构不一相互赋值 分类:数组、对象、字符串、布尔值、函数参数、数值等解构赋值
{
let a, b, rest;
[a, b] = [1, 2];
console.log(a, b);
// 输出1 2
}
{
let a, b, rest;
[a, b, ...rest] = [1, 2, 3, 4, 5, 6];
console.log(a, b, rest);
// 输出1 2 [3,4,5,6]
}
// 对象解构赋值
{
let a, b;
({ a, b } = { a: 1, b: 2 })
console.log(a, b);
// 输出1 2
}
{
let a, b, c, rest;
[a, b, c = 3] = [1, 2];
console.log(a, b, c);
// 输出1 2 3 解构元素没有配对时为undefined
}
{
let a = 1;
let b = 2;
[a, b] = [b, a]
console.log(a, b);
// 输出2 1 解构赋值方便两个变量值的交换
}
{
function f() {
return [1, 2]
}
let a, b;
[a, b] = f();
console.log(a, b);
// 输出1 2
}
{
function f() {
return [1, 2, 3, 4, 5]
}
let a, b, c;
[a, , , b] = f();
console.log(a, b);
// 输出1 4 选择性接受变量
}
// 对象解构
{
let o = { p: 42, q: true };
let { p, q } = o;
console.log(p, q);
}
{
let { a = 10, b = 5 } = { a: 3 };
console.log(a, b);
// 输出3 5 后覆盖前
}
{
let metaData = {
title: 'abc',
test: [{ title: 'test', desc: 'description' }]
}
let { title: esTitle, test: [{ title: cnTitle }] } = metaData;
console.log(esTitle, cnTitle);
//输出'abc''test'
}
//正则扩展 构造函数的变化 正则方法的扩展 u修饰符 y修饰符 s修饰符
{
let regex = new RegExp('xyz', 'i');//es5
let regex2 = new RegExp(/xyz/i);//es5 正则表达式,该写法只能有一个参数
console.log(regex.test('xyz123'), regex2.test('xyz1223'));//true
let regex3 = new RegExp(/xyz/ig, 'i');//es6可以有两个参数,后面的修饰符会覆盖前面的
console.log(regex3.flags);//输出i,flags用来获取正则表达式的修饰符
}
// y修饰符 与g一样都是全局匹配符,g从上次匹配到的位置开始找下一个匹配的,g就是上次匹配的位置开始就要求匹配
{
let s = 'bbb_bb_b';
let a1 = /b+/g;
let a2 = /b+/y;
console.log('one', a1.exec(s), a2.exec(s));//bbb,bbb
console.log('one', a1.exec(s), a2.exec(s));//bb,null(_)
console.log(a1.sticky, a2.sticky);//false,true判断是否开启y修饰符
}
//u特征值 识别unicode编码
{
console.log('u-1', /^\uD83D/.test('\uD83D/\uDC2A/'));//true 两个字符
console.log('u-1', /^\uD83D/u.test('\uD83D/\uDC2A/'));//false 一个字符
console.log(/\u{61}/.test('a'));//false
console.log(/\u{61}/u.test('a'));//true
console.log('\u{20887}');
let s = '?';
console.log('u', /^.$/.test(s));//false ‘.’只能匹配小于两个字节,且不能识别/t,/n加s修饰符
console.log('u-2', /^.$/u.test(s));//true 大于两字节则需要u修饰符
console.log('test', /?{2}/.test('??'));//false
console.log('test', /?{2}/u.test('??'));//true
}
// 字符串扩展 新增特性 Unicode表示法 遍历接口 模板字符串 新增方法(10种)
// npm install babel-polyfill --save-dev 安装补丁库
{
console.log('a', '\u0061');//a a
console.log('s', "\u20BB7");// ₻7 大于#0xffff,分开显示
console.log('s', "\u{20BB7}");// ?
}
//
{
let s = '?';
console.log("length", s.length);//length 2
console.log("0", s.charAt(0));//0 �
console.log("1", s.charAt(1));//1 �
console.log("0", s.charCodeAt(0));//0 55362 es6新增,取码值,只取2字节
console.log("1", s.charCodeAt(1));//1 57271
let s1 = '?a';
console.log('length', s1.length);//length 3
console.log("0", s1.codePointAt(0));//0 134071
console.log("0", s1.codePointAt(0).toString(16));//0 20bb7
console.log("1", s1.codePointAt(1));//1 57271
console.log("1", s1.codePointAt(1).toString(16));//1 dfb7
console.log("2", s1.codePointAt(2));//97
}
{
console.log(String.fromCharCode("0x20bb7"));//es5 ஷ乱码
console.log(String.fromCodePoint("0x20bb7"));//es6 ?
}
{
let str = '\u{20bb7}abc';
for (let i = 0; i < str.length; i++) {
console.log('es5', str[i]);
}//es5 � 3 es5 � es5 a es5 b es5 c
for (let code of str) {
console.log('es6', code);
}//es6 ? es6 a es6 b es6 c
}
//判断起始字符串和截至字符串
{
let str = 'string';
console.log("include", str.includes("r"));//true 包含
console.log("start", str.startsWith("str"));//true 开始
console.log("start", str.endsWith("ng"));//true 截至
}
//重复
{
let str = 'string';
console.log(str.repeat(2));//stringstring
}
//es7草案
{
let name = "list";
let info = "hello world"
let m = `i am $(name),$(info)`;
console.log(m);
}
//补白,padStart(2---位数, '0'----补白替代字)
{
console.log('1'.padStart(2, '0'));//01 往前面补白
console.log('1'.padEnd(2, '0'));//10 往后面补白
}
//标签模板 1.过滤字符串,防止xss攻击;2.处理多语言转换的时候
{
let user = {
name: 'list',
info: 'hello world'
};
abc`i am $(user.name),$(user.info)`;
console.log(abc`i am $(user.name),$(user.info)`)
function abc(s, v1, v2) {
console.log(s, v1, v2);
return s + v1 + v2
}
}
{
console.log(String.raw`Hi\n$(1+2)`);//Hi\n$(1+2)
console.log(`Hi\n$(1+2)`);//Hi $(1+2)
}
//数值扩展 1.新增方法 2.方法调整
{
//不区分大小写
console.log(0b111110111);//503 二进制
console.log(0o767);//503 八进制
}
{//Number.isFinite 是否有尽
console.log('15', Number.isFinite(15));//15 true
console.log('NaN', Number.isFinite(NaN));//15 false 不是数
console.log('1/0', Number.isFinite(1 / 0));//1/0 false
// Number.isNaN 判断是不是数字
console.log('0', Number.isNaN(0));//false
// Number.isInteger判断是不是整数 接受的参数必须是数字
console.log('0.0', Number.isInteger(0.0));//true
console.log('0.1', Number.isInteger(0.1));//false
}
{
// 判断数字是否在-2的53次方,2的53次方
console.log(Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);
console.log('10', Number.isSafeInteger(10));//true
console.log('a', Number.isSafeInteger(a));//false
}
{
// Math.trunc分离,取整
console.log('4.1', Math.trunc(4.1));//4
console.log('4.1', Math.trunc(4.9));//4
}
{
//Math.sign判断正数负数还是零,返回 1,0,-1
console.log('-5', Math.sign(-5));//-1
console.log('-5', Math.sign('-5'));//-1
console.log('a', Math.sign('a'));//NaN
}
{
// 计算立方根
console.log('-1', Math.cbrt(-1));//-1
console.log('8', Math.cbrt(8));//2
}
// 数组扩展 Array.from Array.of copyWithin find\findIndex fill entries\keys\values includes
{
let arr = Array.of(3, 4, 7, 9, 11);
console.log('arr=', arr);//arr= (5) [3, 4, 7, 9, 11]
let empty = Array.of();
console.log('empty=', empty);//empty= []
}
{// 数组扩展 Array.from 伪数组,集合转化为数组 ;映射
{/* <p></p>
<p></p> */}
let p = document.querySelectorAll('p');
let pArr = Array.from(p);
pArr.forEach(function (item) {
console.log(item.textContent);
})
console.log(Array.from([1, 3, 5], function (item) { return item * 2 }))//(3) [2, 6, 10]
}
{
//填充数组
console.log('fill-7', [1, 'a', undefined].fill(7));//fill-7 (3) [7, 7, 7]
// 第一个开始换到三个
console.log('fill,pos', ['a', 'b', 'c'].fill(7, 2, 3));//fill,pos (3) ["a",'b', 7]
console.log('fill,pos', ['a', 'b', 'c', 'd'].fill(7, 1, 3));//fill,pos (4) ["a", 7, 7, "d"]
}
{//entries\keys\values
for (let index of ['1', 'c', 'ks'].keys()) {//索引
console.log('keys', index);//keys 0 keys 1 keys 2
}
for (let value of ['1', 'c', 'ks'].values()) {//值
console.log('values', value);//values 1 values c values ks
}
for (let [index, value] of ['1', 'c', 'ks'].entries()) {//both
console.log('values', index, value);//values 0 1 values 1 c values 2 ks
}
}
{//从0开始 截止到4,即4之前(3,4】
console.log([1, 2, 3, 4, 5].copyWithin(0, 3, 4));//(5) [4, 2, 3, 4, 5]
}
{//只找到第一个
console.log([1, 2, 3, 4, 5].find(function (item) { return item > 3 }));//4
console.log([1, 2, 3, 4, 5].findIndex(function (item) { return item > 3 }));//3
}
{
console.log('number', [1, 2, NaN].includes(NaN));//number true
}
// 函数扩展 参数默认值 rest参数 扩展运算符 箭头函数 this绑定 尾调用
{//默认值后面不能有误默认值的变量参数
function test(x, y = 'world') {
console.log('默认值', x, y);
}
test('hello');//默认值 hello world
test('hello', 'kity');//默认值 hello kity
}
{
let x = 'test';
function test2(x, y = x) {
console.log('作用域', x, y);
}
test2('kity');//作用域 kity kity 这里
}
{//不确定参数都转化为数组 之后不能有别的参数
function test3(...arg) {
for (let v of arg) {
console.log('rest', v);
}
}
test3(1, 2, 3, 4, 'a');//rest 1 rest 2 rest 3 rest 4 rest a
}
{//将数组拆分成离散的值
console.log(...[1, 2, 4]);//1 2 4
console.log('a', ...[1, 2, 4]);//a 1 2 4
}
{//arrow函数名 v函数参数,无参用() v*2函数返回值
let arrow = v => v * 2;
console.log('arrow', arrow(3));//arrow 6
}
{//尾调用
function tail(x) {
console.log('tail', x);
}
function fx(x) {
return tail(x)
}
fx(123);//tail 123
}
// 对象扩展 函数新增特性 简洁表示、属性表达式、扩展运算符、Object新增方法
{
// 简洁表示法
let o = 1;
let k = 2;
let es5 = {
o: o,
k: k
}
let es6 = {
o, k
};
console.log(es5, es6);//{o: 1, k: 2} {o: 1, k: 2}
//对象里面有方法
let es5_method = {
hello: function () {
console.log('hello');
}
};
let es6_method = {
hello() {
console.log('hello');
}
};
console.log(es5_method.hello(), es6_method.hello());//hello hello
}
{//属性表达式
let a = 'b';
let es5_obj = {
a: 'c',
b: 'c'
}
let es6_obj = {
[a]: 'c'
}
console.log(es5_obj, es6_obj)//{a: "c", b: "c"} {b: "c"}
}
{//新增API Object.is相当于===
console.log('字符串', Object.is('abc', 'abc'));
console.log('数组', Object.is([], []));//false
//不会拷贝继承的属性,
console.log('拷贝', Object.assign({ a: 'a' }, { b: 'b' }));//拷贝 {a: "a", b: "b"}
let test = { k: 123, o: 456 };
for (let [key, value] of Object.entries(test)) {
console.log([key, value]);//["k", 123] ["o", 456]
}
}
{//扩展运算符
let { a, b, ...c } = { a: 'test', b: 'kill', c: 'ddd', d: 'ccc' };
console.log(c)//{c: "ddd", d: "ccc"}
}
// Symbol给该数据类型提供一个唯一的值
{
let a1 = Symbol();
let a2 = Symbol();
console.log(a1 === a2);//false
//a3是key值
let a3 = Symbol.for('a3');
let a4 = Symbol.for('a3');
console.log(a3 === a4);//true
}
{
let a1 = Symbol.for('abc');
let obj = {
[a1]: '123',
'abc': 345,
'c': 456
};
console.log('obj', obj);//obj {abc: 345, c: 456, Symbol(abc): "123"}
for (let [key, value] of Object.entries(obj)) {
console.log('let of', key, value);//let of abc 345 ,let of c 456
}
Object.getOwnPropertySymbols(obj).forEach(function (item) {
console.log(obj[item]);//123
})
Reflect.ownKeys(obj).forEach(function (item) {
console.log('ownkeys', item, obj[item]);//ownkeys abc 345,ownkeys c 456,ownkeys Symbol(abc) 123
})
}
// 数据结构 Set :WeakSet(当做数组,集合中的元素不能重复) ;Map: WeakMap(object,一个key一个value,object中key一定是字符串,map随意)
{
let list = new Set();
list.add(5);
list.add(7);
console.log('size', list.size);//size 2;size相当于length
}
{
let arr = [1, 2, 3, 4, 5];
let list = new Set(arr);
console.log('size', list.size);//size 5;
}
{//可以用来去重,但是不会做数据类型的转换
let list = new Set();
list.add(1);
list.add(2);
list.add(1);
console.log('list', list);//list Set(2) {1, 2}
let arr = [1, 2, 3, 1, 2, '2'];
let list2 = new Set(arr);
console.log('unique', list2);//unique Set(3) {1, 2, 3,'2}
}
{
let arr = ['add', 'delete', 'clear', 'has'];
let list = new Set(arr);
console.log('has', list.has('add'));//has true
console.log('delete', list.delete('add'), list);//delete true Set(3) {"delete", "clear", "has"}
console.log('clear', list.clear(), list);//clear undefined Set(0) {}
}
{
let arr = ['add', 'delete', 'clear', 'has'];
let list = new Set(arr);
for (let key of list.keys()) {
console.log('keys', key);//keys add;keys delete;keys clear;keys has
}
for (let value of list.values()) {
console.log('value', value);//value add;value delete;value clear;value has
}
for (let [key, value] of list.entries()) {
console.log('entries', key, value);//entries add add ;entries delete delete;entries clear clear;entries has has
}
list.forEach(function (item) { console.log(item); })//add delete clear has
}
{//WeakSet set支持的元素不同 ,WeakSet只能是对象,不能是数值、布尔值等;不会检测重复元素
let weakList = new WeakSet();//没有size属性
let arg = {}
weakList.add(arg);
console.log('', weakList);//WeakSet {{…}}
}
{//map添加元素用set(key,value) ;set添加元素用add
let map = new Map();
let arr = ['123'];
map.set(arr, 456);
console.log('map', map, map.get(arr));//map Map(1) {Array(1) => 456} 456
}
{//遍历同set
let map = new Map([['a', 123], ['b', 456]]);
console.log('map args', map);//map args Map(2) {"a" => 123, "b" => 456}
console.log('size', map.size);//size 2
console.log('delete', map.delete('a'), map);//delete true Map(1) {"b" => 456}
console.log('clear', map.clear(), map);//clear undefined Map(0) {}
}
{//必须是对象,没有size,不能clean
let weakmap = new WeakMap();
let o = {}
weakmap.set(o, 123);
console.log(weakmap.get(o));//123
}
// 数据结构 map与array的对比 set与array的对比
{//map与array的对比
let map = new Map();
let array = [];
//增
map.set('t', 1);
array.push({ t: 1 });
console.info('map-array', map, array);//map-array Map(1) {"t" => 1} [{…}]
// 查
let map_exist = map.has('t');
let array_exist = array.find(item => item.t);
console.info('exist', map_exist, array_exist);//exist true {t: 1}
// 改
map.set('t', 2);
array.forEach(item => item.t ? item.t = 2 : '');//遍历是否存在,再修改
console.info('map-array', map, array);//map-array Map(1) {"t" => 2} [{t:2}]
// 删
map.delete('t');
let index = array.findIndex(item => item.t);
array.splice(index, 1);//必须查到索引后删除
console.log('map-array', map, array);//map-array Map(0) {} []
}
{//set与array的对比
let set = new Set();
let array = [];
//增
set.add({ t: 1 });
array.push({ t: 1 });
console.log('set-array', set, array);//set-array Set(1) {{…}}size: 1__proto__: Set[[Entries]]: Array(1)0: Objectlength: 1 [{…}]
// 改
set.forEach(item => item.t ? item.t = 2 : '');
array.forEach(item => item.t ? item.t = 2 : '');
console.log('set-array', set, array);//set-array Set(1) {{…}}size: 1__proto__: Set[[Entries]]: Array(1)0: Objectlength: 1 [{…}]
// 查
let set_exist = set.has({ t: 1 });
let array_exist = array.find(item => item.t);
console.log('set-array', set_exist, array_exist);//set-array false {t: 2}
// 删
set.forEach(item => item.t ? set.delete(item) : '');
let index = array.findIndex(item => item.t);
array.splice(index, 1);//必须查到索引后删除
console.log('set-array', set, array);//set-array Set(0) {} []
}
//数据结构 map与object set 与object
{
let item = { t: 1 };
let map = new Map();
let set = new Set();
let obj = {};
//add
map.set('t', 1);
set.add(item);
obj['t'] = 1;
console.info('map-set-ob', obj, map, set);//map-set-ob {t: 1} Map(1) {"t" => 1} Set(1) {{…}}
//check
console.log({
map_exist: map.has('t'),
set_exist: set.has(item),
obj_exist: 't' in obj
})//{map_exist: true, set_exist: true, obj_exist: true}
//change
map.set('t', 2);
item.t = 2;
obj['t'] = 2;
console.info('map-set-ob', obj, map, set);//map-set-ob {t: 2} Map(1) {"t" => 2} Set(1) {{…}}
//delete
map.delete('t');//成本最低
set.delete('t');
delete obj['t'];
console.info('map-set-ob', obj, map, set);//map-set-ob {} Map(0) {} Set(1) {{…}}
}//总结,优先使用map,如果对数据要求严格(唯一性)使用set放弃object和传统的数组
// Proxy 代理(连接用户和对象) 和 Reflect(反射),两者方法相同
{
let obj = {//供应商,原始对象
time: '2017-03-11',
name: 'net',
_r: 123
};
// 代理商
let monitor = new Proxy(obj, {
// 方法 target指的是obj对象;key修改哪个属性;value指的是值设置为什么
// 拦截(代理)对象属性的读取
get(target, key) {
return target[key].replace('2017', '2018')
},
//拦截对象设置属性
set(target, key, value) {
if (key === 'name') {
return target[key] = value;
} else {
return target[key];
}
},
//拦截key in object操作
has(target, key) {//只暴露name属性
if (key === 'name') {
return target[key]
} else {
return false;
}
},
// 拦截delete
deleteProperty(target, key) {
if (key.indexOf('_') > -1) {
delete target[key];
return true;
} else {
return target[key]
}
},
// 拦截 Object.keys;Object.getOwnPropertySymbols;Object.getOwnPropertyNames
ownKeys(target) {
return Object.keys(target).filter(item => item != 'time')
}
});
// 用户操作
console.log('get', monitor.time);//get 2018-03-11
monitor.time = '2019';
monitor.name = 'hello'
console.log('set', monitor.time, monitor);//set 2018-03-11 Proxy {time: "2017-03-11", name: "hello", _r: 123}
console.log('has', 'name' in monitor, 'time' in monitor);//has true false
delete monitor.time;
console.log('deleter', monitor);//deleter Proxy {time: "2017-03-11", name: "hello", _r: 123}
delete monitor._r;
console.log('deleter', monitor);//deleter Proxy {time: "2017-03-11", name: "hello"}
console.log('ownKeys', Object.keys(monitor));//ownKeys (2) ["name", "_r"]
}
{
let obj = {//供应商,原始对象
time: '2017-03-11',
name: 'net',
_r: 123
};
console.log('Reflect get', Reflect.get(obj, 'time'));//Reflect get 2017-03-11
Reflect.set(obj, 'name', 'hello');
console.log(obj);//{time: "2017-03-11", name: "hello", _r: 123}
console.log('has', Reflect.has(obj, 'name'));//has true
}
{//解耦
function validator(target, validator) {
return new Proxy(target, {
_validation: validator,
set(target, key, value, proxy) {
if (target.hasOwnProperty(key)) {
let va = this._validation[key];
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('lilei', 30);
console.info(person);//Proxy {name: "lilei", age: 30}
// person.name = 48;//Uncaught Error: 不能设置$(key)到$(value)
}
//类与对象 类:基本语法;类的继承;静态方法;静态属性;getter;setter;
{
// 基本定义和生成实例 class关键字定义类,constructor定义属性
class Parent {
constructor(name = 'laowang') {
this.name = name;
}
}
let v_parent = new Parent('v');//实例
console.log('构造函数和实例', v_parent);//构造函数和实例 Parent {name: "v"}
}
{
// 继承
class Parent {
constructor(name = 'laoli') {
this.name = name;
}
}
class Child extends Parent {
}
console.log('继承', new Child());//继承 Child {name: "laoli"}
}
{
// 继承传递参数
class Parent {
constructor(name = 'laoli') {
this.name = name;
}
}
class Child extends Parent {
constructor(name = 'child') {
super(name);//super一定放在构造函数的第一行
this.type = 'child';
}
}
console.log('继承', new Child('hello'));//继承 Child {name: "hello", type: "child"}
}
{//getter,setter
class Parent {
constructor(name = 'laoli') {
this.name = name;
}
get longName() {//并不是方法,是属性
return 'mk' + this.name
}
set longName(value) {
this.name = value;
}
}
let v = new Parent();
console.log('getter', v.longName);//getter mklaoli
v.longName = 'hello';
console.log('setter', v.longName);//setter mkhello
}
{//静态方法
class Parent {
constructor(name = 'laoli') {
this.name = name;
}
static tell() {//静态方法通过类去调用,而不是类的实例去调用
console.log('tell');
}
}
Parent.tell();//tell
}
{//静态属性
class Parent {
constructor(name = 'laoli') {
this.name = name;
}
static tell() {//静态方法通过类去调用,而不是类的实例去调用
console.log('tell');
}
}
//静态属性定义没有关键词
Parent.type = 'test';
console.log('静态属性', Parent.type);//静态属性 test
}
// Promise 异步:a执行完后b执行:1.回调;2.事件触发(Promise区别于这两种更适用于异步操作)
{//回调方式,基本定义,难以维护
let ajax = function (callback) {
console.log('执行');
setTimeout(function () {
callback && callback.call()
}, 1000);
};
ajax(function () {
console.log('timeout1');
})
}
{//resolve执行操作; reject中断操作
let ajax = function () {
console.log("执行2");
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve()
}, 1000);
})
}
ajax().then(function () {
console.log('promise', 'timeout2');
})
}
{
let ajax = function () {
console.log("执行2");//第一步
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve()
}, 1000);
})
}
ajax().then(function () {
console.log("执行3");//第二步
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve()
}, 2000);
}).then(function () {
console.log('timeout3')//第三步
})
})
}
{//异常报错
let ajax = function (num) {
console.log('执行4');
return new Promise(function (resolve, reject) {
if (num > 5) {
resolve()
} else {
throw new Error('出错了')
}
})
}
ajax(5).then(function () {
console.log('log', 6);
}).catch(function (err) {
console.log('catch', err);
})
}
// 这里是一个实战啊
{//所有图片加载完之后再添加到页面
function loadImg(src) {
return new Promise((resolve, reject) => {
let img = document.createElement('img');
img.src = src;
img.onload = function () {
resolve(img);
},
img.onerror = function (err) {
reject(err);
}
})
}
function showImg(imgs) {
imgs.forEach(function (img) {
document.body.appendChild(img);
})
}
//all将多个Promise实例当做一个实例
Promise.all([
loadImg('http://i4.buimg.com/567571/df1ef0720bea6803.png'),
loadImg('http://i4.buimg.com/567751/2b07ee25b08930ba.png'),
loadImg('http://i4.buimg.com/567571/df1ef0720bea6803.png')
]).then(showImg)
}
{//有一个图片加载完就显示到页面
function loadImg(src) {
return new Promise((resolve, reject) => {
let img = document.createElement('img');
img.src = src;
img.onload = function () {
resolve(img);
},
img.onerror = function (err) {
reject(err);
}
})
}
function showImg(img) {
let p = document.createElement('p');
p.appendChild(img);
document.body.appendChild(p)
}
// race只要有一个改变,其他都不在响应
Promise.race([
loadImg('http://i4.buimg.com/567571/df1ef0720bea6803.png'),
loadImg('http://i4.buimg.com/567751/2b07ee25b08930ba.png'),
loadImg('http://i4.buimg.com/567571/df1ef0720bea6803.png')
]).then(showImg)
}
// Iterator 和 for...of循环
{//Iterator
let arr = ['hello', 'world'];
let map = arr[Symbol.iterator]();
console.log(map.next());//{value: "hello", done: false}
console.log(map.next());//{value: "world", done: false}
console.log(map.next());//{value: undefined, done: true}
}
{//对象
let obj = {
start: [1, 3, 2],
end: [1, 8, 9],
[Symbol.iterator]() {//声明接口方法
let self = this;
let index = 0;
let arr = self.start.concat(self.end);
let len = arr.length;
return {
next() {
if (index < len) {
return {
value: arr[index++],
done: false
}
} else {
return {
value: arr[index++],
done: true
}
}
}
}
}
}
for (let key of obj) {
console.log(key);//132189
}
}
{
let arr = ['hello', 'world'];
for (let value of arr) {
console.log('value', value);//value hello ;value world
}
}
//Generator异步编程解决方案
// 遍历器生成函数,可以直接赋值给iterator接口。
{//基本定义 是一个函数,返回的是iterator接口,执行一次next,调用一次yield
let tell = function* () {
yield 'a';
yield 'b';
return 'c';
};
let k = tell();
console.log(k.next());//{value: "a", done: false}
console.log(k.next());//{value: "b", done: false}
console.log(k.next());//{value: "c", done: true}
console.log(k.next());//{value: undefined, done: true}
}
// 使用Generator做遍历器
{
let obj = {};
obj[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3
}
for (let value of obj) {//遍历
console.log(value);// 1 2 3
}
}
{//状态机(Generator最大的优势) 这里:三种状态循环
let state = function* () {
while (1) {
yield 'A';
yield 'B';
yield 'C';
}
}
let status = state();
console.log(status.next());//A
console.log(status.next());//B
console.log(status.next());//C
console.log(status.next());//A
}
{
let state = async function () {
while (1) {
await 'A';
await 'B';
await 'C';
}
}
let status = state();
console.log(status.next());//A
console.log(status.next());//B
console.log(status.next());//C
console.log(status.next());//A
}
{//实例:抽奖次数限制
let draw = function (count) {
//具体抽奖逻辑
console.info('剩余${count}次')
}
let residue = function* (count) {
while (count > 0) {
count--;
yield draw(count);
}
}
let star = residue(5);
let btn = document.createElement('button');
btn.id = 'start';
btn.textContent = '抽奖';
document.body.appendChild(btn);
document.getElementById('start').addEventListener('click', function () {
star.next();
}, false)
}
{
//长轮询,Generator结合Promise
let ajax = function* () {
yield new Promise(function (resolve, reject) {
setTimeout(function () {
resolve({ code: 0 })
}, 200);
})
}
//轮询过程
// 补充,服务端http是一个无状态的过程,获取服务端的状态变化websocket(浏览器兼容性不好)和长轮询
let pull = function () {
let generator = ajax();
let step = generator.next();
step.value.then(function (d) {
if (d.code != 0) {
setTimeout(function () {
console.log('wait');
pull()
}, 1000);
} else {
console.log(d);
}
})
}
pull();
}
// Decorator修饰器是一个函数,用来修改类的行为(扩展类的功能)
//npm babel-plugin-transform-decorators-legacy --save-dev
{//参数 1.类本身 2.名称 3.该属性的描述对象
let readonly = function (target, name, descriptor) {
descriptor.writable = false;
return descriptor
};
class Test {
@readonly
time() {
return '2017-03-11'
}
}
let test = new Test();
test.time = function () {
console.log('reset time');//这里会报错,不允许修改
}
console.log(test.time());
}
{
let typename = function (target, name, descriptor) {
target.myname = 'hello';//类的静态属性
}
@typename
class Test {
}
console.log('类修饰符', Test.myname);
//第三方库修饰器的js库,core-decorators
}
{//案例:日志系统
let log = (type) => {
return function (target, name, descriptor) {
let src_method = descriptor.value;
descriptor.value = (...arg) => {
src_method.apply(target, arg);
console.info(`log $(type)`);//模拟买点,new image.src="接口"
}
}
}
class AD {
@log('show')
show() {
console.info('ad is show')
}
@click('click')
click() {
console.info('ad is click');
}
}
let ad = new AD();
ad.show();
ad.click();
}
// 模块化 import引入 export导出
{//方式一
export let A = 123;
export function test() {
console.log('test');
}
export class Hello {
test() {
console.log('class')
}
}
import { A, test, hello } from './'
import * as lesson from './'//导入所有
console.log(lesson.A, lesson.test)
}
{//方式二
{
let A = 123;
function test() {
console.log('test');
}
class Hello {
test() {
console.log('class')
}
}
export default {
A,
test,
Hello
}
import lesson17 from './' //无需命名与前面相同
}
}