一、let、const、块作用域
let-cont相同点:
1.强制使用严格模式;
2.不能重复声明同意变量。
3.都能在 {} 块作用域中生效;(即作用域范围是:{} )
const:
1.声明5中基本类型之后,便不能修改值;但是声明变量,则存储的是对象的内存地址。
2.初始化时,必须赋值。
二、解构赋值 :对象和数组
共同点:
1.无匹配时返回undefined;
2.可以设置默认值;
3.优先级:赋值 > 设置的默认值 .> 无匹配时的undefined
数组解构:
let [a, b, ...c] = [1,2,3,4]; // a=1,b=2,c=[3,4]
应用场景:(数组值的对换)
let a = 1;
let b = 2;
[a, b] = [b, a]; //a=2,b=1
对象解构:重命名的name写在对象的value中;
let data = {
title: 'abc',
list: [
{
title: 'test...',
des: 'des...'
}
]
}
//拿到 第一层的title和第二层的title
let {title,list: [{title: cnTitle}]} = data; //title='abc',cnTitle='test...'
三、正则的拓展
构造函数的拓展:
1.可以在构造函数的1参和2参添加修饰符;2参>1参(2参会覆盖1参)
2.reg.flags
:修饰符的查询;(其中reg是一个正则的实例)
let r1 = new RegExp(/a/);
let r2 = new RegExp(/a/i);
let r3 = new RegExp(/a/i, 'g');
let str1 = 'AbcAd';
console.log( r1.test(str1), r1.flags ); //false ''
console.log( r2.test(str1), r2.flags ); //true 'i'
console.log( r3.test(str1), r3.flags ); //false 'g' [产生了覆盖]
y修饰符: 更加严格的匹配,第一次和第二次匹配中间不能有任何的间隔。
reg.sticky
: 是否使用y修饰符。
let r1 = /a/i;
let r2 = /a/iy;
let s1 = 'AbAc';
let s2 = 'AAc';
console.log(r1.test(s1), r1.sticky); //true false
console.log(r2.test(s1), r2.sticky); //true true
console.log(r1.test(s1), r1.sticky); //true false
console.log(r2.test(s1), r2.sticky); //false true [匹配更加严格,中间不能有任何间隙]
console.log(r1.test(s2 ), r1.sticky); //true false
console.log(r2.test(s2 ), r2.sticky); //true true
console.log(r1.test(s2 ), r1.sticky); //true false
console.log(r2.test(s2 ), r2.sticky); //true true [中间没有任何间隙]
[补充]:字符的定义:字符是指计算机中使用的字母、数字、字和符号
在 ASCII 编码中,一个英文字母字符存储需要1个字节。在 GB 2312 编码或 GBK 编码中,一个汉字字符存储需要2个字节。在UTF-8编码中,一个英文字母字符存储需要1个字节,一个汉字字符储存需要3到4个字节。在UTF-16编码中,一个英文字母字符或一个汉字字符存储都需要2个字节(Unicode扩展区的一些汉字存储需要4个字节)。在UTF-32编码中,世界上任何字符的存储都需要4个字节。
[补充]:1字符 == 2字节 == 4个十六进制字母
let a = '稳';
let b = a.charCodeAt(0); //转unicode编码
let c = b.toString(16); //将unicode编码转十六进制
console.log(b, c); //31283 '7a33' “稳”字的unicode码,十六进制
console.log( b.fromCharCode(b) ); //稳
console.log( b.fromCharCode('0x'+c) ); //稳
在Unicode编码下的例子:
稳(1字符) == 2字节 [7a,33] == 4个十六进制字符[7,a,3,3]
u修饰符:匹配unicode字符,处理大于2字节长度的字符。
下面乱码的字符是: ,unicode十六进制是:20bb7,可以使用 String.fromCodePoint('0x20bb7')
方法转回字符(此方法为ES6方法)
let a = '?'; //unicode码字符大于4字节
let b = a.codePointAt(0); //134071
let c= b.toString(16); //20bb7
console.log( /u{20bb7}/.test('?') ); //false
console.log( /u{20bb7}/u.test('?') ) //true
s修饰符: s修饰符,可以使 点(.)匹配
字符
正则中,点(.)是一个特殊字符,代表任意的单个字符,但是行终止符除外:
// U+000A 换行符(
)
// U+000D 回车符(
)
// U+2028 行分隔符(line separator)
// U+2029 段分隔符(paragraph separator)
只是一个提案目前还不支持,es8中实现
let r1=/test.go/s;
let r2=/test.go/;
let s = 'test
go';
console.log(r1.test(s)); //true
console.log(r2.test(s)); //false
四、字符串的拓展
下面乱码的字符是: ,unicode十六进制是:20bb7,可以使用 String.fromCodePoint('0x20bb7')
方法转回字符(此方法为ES6方法)
[补充]:.length属性: 计算长度时,每2个字节为一个字符。
let a = '稳';
let b = String.fromCodePoint('0x20bb7');
console.log(a.length); // 1
console.log(b.length); // 2
[补充]:ES5转码方法介绍: (只能转<=2个字节的字符)
-
str.charAt(0)
返回第0位的字符; -
str.charCodeAt(0)
返回第0位字符的Unicode编码,可以使用.toString(16)
转16进制; -
String.fromCharCode()
将Unicode编码转字符串,十六进制转法:str.fromCharCode('0x'+'7a33')
let str = '稳';
console.log( str.charAt(0) ); //稳
console.log( str.charCodeAt(0) ); // 31283
console.log( String.fromCharCode(31283) ) //稳
ES6转码方法介绍: (可以转> || <= 2个字节的字符)
-
str.codePointAt(0)
将第0位转Unicode吗 -
str.fromCodePoint()
将Unicode码转字符串 -
for...of
—> 可以正确的解析 > || <= 2字节的字符。
let @a = String.fromCodePoint('0x20bb7'); //@a 即上面几例中的乱码字符,使用这个方法就可以得到这个字符
let a = @a.charCodeAt(0); //31283
let b = @a.codePointAt(0); //134071
String.fromCharCode(a); // �
String.fromCodePoint(b); // @a ---> 这里代指 @a表示的字符,因为这个编辑器输出这个字符会乱码
字符串的检测:
1.str.includes('s')
—> str
中是否包含s
2.str.startWith('st')
—>str
是否以st
开头
str.endWith('ing')
—>str
中是否以ing
结尾
let s = 'string';
console.log( s.includes('tr') ) //ture
console.log( s.includes('ti') ) //false [测试不连续的字符]
console.log( s.startsWith('st') ) //true
console.log( s.startsWith('sr') ) //false [测试不连续的字符]
console.log( s.endsWith('ing') ) //true
console.log( s.endsWith('ig') ) //false [测试不连续的字符]
模板字符串:
1.
let str = 'david';
`I am ${str}` // I am david 为变量
- 2.
function add(){
console.log(arguments);
}
let user = {
name: 'david',
info: 'man'
}
add`I am ${user.name},${user.info}`
//arguments ---> ['I am ',',',''] 'david' 'man'
补位:(ES7)指定长度2,不够的补’0’
1.'1'.padStart(2,'0')
—> 输出为:’01’
2.'1'.padEnd(2,'0')
—> 输出为:’10’
let s1 = '1';
let s2 = '1.';
s1.padStart(3, ''); // '1'
s1.padStart(1, '0'); // '1'
s1.padStart(2, '0'); // '01'
s2.padEnd(2, '0'); // '1.'
s2.padEnd(3, '0'); // '1.0'
五、数值的拓展
[补充]:二进制<—>十进制、八进制<—>十进制 的相互转化:
let a = 20;
let b = a.toString(2); // 10100 {二进制}
let c = parseInt(b, 2); // 20 {十进制}
let d = a.toStrging(8); // 24 {八进制}
let e = parseInt(d, 8); // 20 {十进制}
二进制和八进制的表示方法:
0b
或者 0B
表示二进制
0o
或者 0O
表示八进制
console.log( 0b10100 ) // 20 输出的时候会被转成10进制
console.log( 0o24 ) // 20
Number对象的属性和方法:
Number.MAX_SAFE_INTEGER
–> 最大 的安全整数
Number.MIN_SAFE_INTEGER
–> 最小 的安全整数
Number.isInteger(number)
· –> 是一个整数? {无类型转换} true(是);false(不是)
Number.isSafeInteger(number)
–> 是一个安全的整数? {无类型转换} true(是);false(不是)
console.log( Number.isInteger(10) ) //true
console.log( Number.isInteger(10.1) )//false
console.log( Number.isSafeInteger(10) ) //true
console.log( Number.isSafeInteger(10.1) ); //false
console.log( Number.MAX_SAFE_INTEGER ) //9007199254740991
console.log( Number.MIN_SAFE_INTEGER ) //-9007199254740991
Math对象的方法:
Math.trunc(Number)
–> 取整 ; [-1,0,1,Infinity,NaN]
Math.sign(number)
–> 判断正负 [1,0,-1,NaN]
Math.cbrt(number)
–> 立方根
console.log( Math.trunc(1.1) ) //1
console.log( Math.trunc(-2.1) ) //-2
console.log( Math.trunc(Infinity) ) //Infinity
console.log( Math.trunc(NaN) ) //NaN
console.log( Math.sign(1.1) ) //1
console.log( Math.sign(-1.1) ) //-1
console.log( Math.sign(0) ) //0
console.log( Math.sign(Infinity) ) //1
console.log( Math.sign(NaN) ) //NaN
console.log( Math.cbrt(8) ) //2
六、数组的拓展
创建:
Array.of(1)
–> 将传入的集合创建为数组;主要是弥补new Array(1),这个方法的缺项。
Array.from(arguments)
–> 将伪数组转为数组
修改:
[1,2,3,4].fill(1,3,4)
–> 将1填充进数组第3位到第4位(不含第四位)
[1,2,3,4,5,6].copyWithin(0,1,3)
–> 取第1-3(不含)位: 2,3 替换 1,2; 最后结果为:[2,3,3,4,5,6]
function add(){
let arr = Array.from(arguments);
console.log( Object.prototype.toString.call(arguments) ) // [object Aguments]
console.log( Object.prototype.toString.call(arr) ) // [object Array]
console.log(arr) // 1,2,3,4,5
arr.fill(1,3,4);
console.log(arr) // 1,2,1,4,5
arr.fill(1,3,5);
console.log(arr) // 1,2,1,1,5
}
add(1,2,3,4,5)
console.log( [1,2,3,4,5,6,7,8].copyWithin(0, 1, 3) ) //[4, 5, 3, 4, 5, 6, 7, 8]
遍历:
1.数组:
[1,2,3].keys()
–> 遍历键
[1,2,3].values()
–>遍历值
[1,2,3].entries()
–>遍历键值
2.对象:
Object.keys(obj)
–>遍历键
Object.values(obj)
–>遍历值
Object.entries(obj)
–>遍历键值
let a = [1,2,3,4];
let b = {
a: 1,
b: 2,
c: 3,
d: 4
}
for( let k of a.keys()){
console.log( k ) // 0,1,2,3
}
for( let v of a.values()){
console.log( v ) // 1,2,3,4
}
for( let [k, v] of a.entries()){
console.log( k, v) // [0,1],[1,2],[2,3],[3,4]
}
for(let k of Object.keys(b)){
console.log( k ) //a,b,c,d
}
for(let v of Object.values(b)){
console.log( v ) //1,2,3,4
}
for(let [k, v] of Object.entries(b)){
console.log( k, v ) //[a,1],[b,2],[c,3],[d,4]
}
检测:
[1,2,3].find(callback(item,index))
–> 找到符合条件的值,只返回第一个
[1,2,3].findIndex(callback(item,index))
–> 找到符合条件的值的下标,只返回第一个
[1,2,NaN].includes(NaN)
–> 检测数组是否有这个值,检测NaN返回true
console.log( [1,2,3,4].find((item,index)=>item>2&&index!=2) ) //4
console.log( [1,2,3,4].findIndex((item,index)=>item>2) ) //2
console.log( [1,2,3,NaN].includes(NaN) ) //true
console.log( [1,2,3,2,NaN].includes(2) ) //true
七、函数的拓展
箭头函数:三种写法
let add = (x,y)=>{return x+y;}
—> //常规写法
let add = x=>{return x+y;}
—> //一个参数时,可以省略 ()
let add = x=>x+y
—> // 函数体只有一句话时,可以省略 {}
,默认将x+y
作为返回值
优势:
1.解决了this
的指向问题;
2.写法更加简洁。
参数默认值:
let add = (x=1,y=2)=>x+y
—> // 给x,y设置了默认参数1,2
rest/spread参数:
//rest
function add(a, ...b){
console.log(a) // 1
console.log(b) // [2,3,4]
}
add(1,2,3,4,5);
//spread
let c = [1,2,3,4];
function add2(a,b,c){
console.log(a,b,c) // 1,2,3
console.log(arguments[3]) // 4
}
add2(...c);
函数的尾调用:提升性能
在函数结束的return
后跟一个函数调用
function b(){ return c(); }
function c(){};
八、对象的拓展
对象简写模式:属性和方法
let obj = {a,add(){}}
,a:属性名是a,属性值是:变量a;add:表示一个函数。
对象属性表达式:属性名是一个可变的值。
新增API:
Object.is(a,b)
,判断a===b? true : false
可以判断NaN
Object.assign(a,b,c)
c覆盖b,b覆盖a,保留a有,b c没有。
Object.entries(obj)
遍历key和value
Object.keys()
遍历key
Object.values()
遍历value
let a = 1;
let b = {
name: 'bb'
}
let c = [1,2,3];
let d = 'dd';
let e = b;
let o1 = {
a,
b,
c,
[d]: 'dd'
}
let o2 = {
a: '11',
b: '22'
}
let o3 = {
b: '222',
c: '333'
}
console.log( o1 )
/*
{
a: 1,
b: {name: "bb"},
c: [1, 2, 3],
d: "dd"
}
*/
console.log( o1[d] ) // dd
console.log( o1.dd ) // dd
console.log( Object.is(1, '1') ); //false [全等]
console.log( Object.is(NaN, NaN) ); //true
console.log( Object.is(b, e) ); //true
// 1.浅拷贝:复制基本类型的值,复制对象类型的内存地址
// 2,后面覆盖前面对象的值,但是保留后面对象没有的值
let f = {
a: '1111'
};
Object.assign(f, o2, o3);
console.log( f )
/*
{
a: '11',
b: '222',
c: '333'
}
*/
console.log(Object.entries(f)) //[['a','11'],['b','222'],['c','333']]
console.log(Object.keys(f)) //['a','b','c']
console.log(Object.values(f)) //['11','222','333']
九、Symbol: [创建独一无二的值]
创建:Symbol.for('aa')
API:
Object.getOwnpropertySymbols(obj)
以数组返回obj
中所有的Symbol 属性
Reflect.ownKeys(obj)
以数组返回obj中所有的普通属性和Symbol 属性
let a = Symbol.for('aa')
let b = Symbol.for('bb')
let o = {
[a]: 1,
aa: 2,
[b]: 3
}
console.log(o)
/*
{
aa: 2,
Symbol(aa): 1
}
*/
console.log( o[a] ) // 1
//Symbol不能被for...in遍历
for(let i in o){
console.log(i) //[aa]
}
console.log( Reflect.ownKeys(o) ); // ['aa', Symbol(aa), Symbol(bb)]
console.log( Object.getOwnPropertySymbols(o) ); // [Symbol(aa), Symbol(bb)]
十、数据解构
Set数据解构:类似数组集合 [‘不能出现重复的数据’]
let arr1 = [1,2,3,4];
let obj1 = {
a: 11,
b: 22
}
let s1 = new Set(arr1); // Set(4) {1,2,3,4}
//增
s1.add(NaN); // Set(4) {1,2,3,4,5}
s1.add(1); // Set(4) {1,2,3,4,5}
//查
s1.has(NaN); //true
s1.has(0); //false
//删
s1.delete(NaN) // Set(4) {1,2,3,4}
s1.clear(); // Set(0) {}
//遍历
s1 = new Set(arr1);
for(let [k, v] of s1.entries()){
console.log( k, v ) //[[1,1], [2,2], [3,3], [4,4]]
}
for(let k of s1.keys()){
console.log( k) //[1,2,3,4]
}
for(let v of s1.values()){
console.log( v ) //[1,2,3,4]
}
for(let value of s1){
console.log(value); //[1,2,3,4]
}
s1.forEach((item, i)=>{
console.log( item, i ) //[[1,1], [2,2], [3,3], [4,4]]
})
WeakSet数据结构:
WeakSet和Set的区别:
// 1:支持的数据类型不一样,WeakSet的元素只能是对象
// 2:WeakSet的元素对象是个弱引用,只是个地址,不会检测这个地址是否被垃圾回收机制回收掉了
// 3:没有size属性,也不能使用clear
// 4:无法遍历
Map数据结构:类似对象 [‘可以使用对象作为属性名’]
let a = [1,2,3];
let o = {
a: 11,
b: 22
}
let c = 'qwe';
let m = new Map();
//增
m.set('a', a).set('o', o).set('c', c) //添加成功 可以理解为:{a: [1,2,3], o: {a: 11, b: 22}, c: 'qwe'};
//查
m.has('a') // true
//改
m.set('a', 'aa'); //aa
//删
m.delete('a');
m.clear();
m.set('a', a).set('o', o).set('c', c);
//遍历
for(let [k, v] of m.entries()){
console.log(k, v); // [ ['a',[1,2,3]], ['o', {a: 11, b: 22}], ['c', 'qwe'] ]
}
for(let k of m.keys()){
console.log(k) // [ 'a', 'o', 'c' ]
}
for(let v of m.values()){
console.log(v) // [ [1,2,3], {a: 11, b: 22}, 'qwe' ]
}
m.forEach((v, k)=> {console.log('forEach', v , k);}) //[ [[1,2,3],'a'], [{a: 11, b: 22}, 'o'], ['qwe', 'c'] ];
WeakMap数据结构:
// WeakMap和Map的区别:
// 1:支持的数据类型不一样,WeakMap的元素只能是对象
// 2:WeakMap的元素对象是个弱引用,只是个地址,不会检测这个地址是否被垃圾回收机制回收掉了
// 3:没有size属性,也不能使用clear
// 4:无法遍历
十一、数据结构的对比
结论:优先使用map
,能使用map
就使用map
,不使用数组,object; 考虑数据存储的唯一性,则使用set
。
{
//数据结构横向对比,map和数组的对比,增删改查
let map=new Map();
let array=[];
//增
map.set('a',1);
array.push({'a':1});
console.log('map-array-insert',map,array); // map-array Map {"a" => 1} [Object]
//查
let map_exist=map.has('a');
let array_exist=array.find(item=>item.a); //返回item.a
console.log('map-array-exist',map_exist,array_exist);//map-array-exist true Object {a: 1}
//改
map.set('a',2);
array.forEach(item=>item.a?item.a=2:'');//遍历每个item,判断key为a的item是否存在,存在则改
console.log('map-array-update',map,array);
//删
map.delete('a');
let index=array.findIndex(item=>item.a);
array.splice(index,1);
console.log('map-array-delete',map,array); // map-array-delete Map {} []
}
{
//数据结构横向对比,Set和数组的对比,增删改查
let set=new Set();
let arr=[];
//增
set.add({t:1});
arr.push({t:1});
console.log('set-array-insert',set,arr); //set-array-insert Set {Object {t: 1}} [Object]
//查
let set_exist=set.has({t:1});
let arr_exist=arr.find(item=>item.t); //返回item.a
console.log('set-array-exist',set_exist,arr_exist);//set-array-exist false Object {t: 1}
//改
set.forEach(item=>item.t?item.t=2:'');
arr.forEach(item=>item.t?item.t=2:'');//遍历每个item,判断key为a的item是否存在,存在则改
console.log('set-array-update',set,arr); //set-array-update Set {Object {t: 2}} [Object]
//删
set.forEach(item=>item.t?set.delete(item):'');
let index=arr.findIndex(item=>item.t);
arr.splice(index,1);
console.log('set-array-delete',set,arr); // set-array-delete Set {} []
}
{
// set,map,object对比
let item={t:1};
let set=new Set();
let map=new Map();
let obj={};
//增
set.add(item);
map.set('t',1);
obj['t']=1;
console.log("set-map-obj",set,map,obj);//set-map-obj Set {Object {t: 1}} Map {"t" => 1} Object {t: 1}
//查
console.log({
'set-exist':set.has(item),
'map-exist':map.has('t'),
'obj-exist':'t' in obj
}); // Object {set-exist: true, map-exist: true, obj-exist: true}
//改
item.t=2; //set元素的修改,因为存储的是地址
map.set('t',2);
obj['t']=2;
console.log("set-map-obj-update",set,map,obj); // set-map-obj-update Set {Object {t: 2}} Map {"t" => 2} Object {t: 2}
//删
set.delete(item);
map.delete('t');
delete obj['t'];
console.log("set-map-obj-delete",set,map,obj); // set-map-obj-delete Set {} Map {} Object {}
}
十二、Proxy:代理对象、Reflect:映射
Proxy:
get(target, key){}
查
set(target, key, value){}
改
deleteProperty(target, key){}
删
has(target, key){}
查
ownKeys(target, key){}
查
let obj = {
name: 'obj',
time: '2018',
age: 24
}
let proxy = new Proxy(obj, {
get(target, key){
if(key === 'age'){
return 0;
}else{
return target[key];
}
},
set(target, key, value){
if(key === 'age'){
return target[key];
}else{
return target[key] = value;
}
},
//拦截for...in
has(target, key){
if(key === 'age'){
return false;
}else{
return target[key];
}
},
deleteProperty(target, key){
if(key === 'age'){
delete target[key];
return true;
}else{
return target[key];
}
},
// 拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames
ownKeys(target){ //只能获取属性不为time的属性
return Object.keys(target).filter(item=>item!='age')
}
})
console.log( proxy.name, proxy.age ) // obj 0
proxy.name = 'obj1'; //修改成功
proxy.age = 0; //修改失败
console.log( 'name' in proxy ) // true
console.log( 'age' in proxy ) // false
delete proxy.name; //删除成功
delete proxy.age; //删除失败
console.log( Object.keys(proxy) ) // [ 'name', 'time' ]
Reflect:
Reflect.get(obj, 'name')
查
Reflect.set(obj, 'age', 0)
改
Reflect.deleteProperty(obj, 'age')
删
Reflect.ownKeys(obj)
查
let obj = {
name: 'obj',
time: '2018',
age: 24
}
let obj = {
name: 'obj',
time: '2018',
age: 24
}
console.log( Reflect.get(obj, 'name') ) //obj
Reflect.set(obj, 'age', 0) //修改成功:age: 0
console.log( Reflect.has(obj, 'time') ) //true
Reflect.deleteProperty(obj, 'age'); //删除成功
console.log( Reflect.ownKeys(obj) ) //['name', 'time']
十三、类和实例
1.构造函数:constructor(){}
实例化时,会执行的函数。
2.继承的关键字:extends
3.子类继承时,必须调用:super
4.定义变量获取/设置方式:get className(){}
和 set className(){}
5.静态方法: static tell() {}
6.静态属性: [className].type = 'class'
,className
是类名
class Person {
constructor(x=1, y = 2){
this.x = x;
this.y = y;
this.name = 'david'
}
get longName(){
return '1 ' + this.name;
}
set longName(val){
this.name = val;
}
static add (){
console.log(111);
}
}
let p = new Person();
p.longName; // '1 daivd'
p.longName = 11; // 11
class Son extends Person{
constructor(x, y){
super(x,y)
}
}
Person.type = 'class';
Person.add(); // 111
Person.type; // class
let s = new Son(8, 9); //{x: 8, y: 9}
十四、异步编程:Promise对象
详细讲解请看另一篇文章:8个例子学会Promise
promise.all([fn1, fn2, fn3])
//其中fn1
、fn2
、fn3
的所的resolve()
之后,执行then()
promise.rece([fn1, fn2, fn3])
//其中fn1
、fn2
、fn3
有一个resolve()
,就执行then()
{
//功能:所有的图片都加载完后再添加到页面里
//加载图片
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 showImgs(imgs){
imgs.forEach(function(img){
document.body.appendChild(img);
})
}
//Promise.all([]) 意思是把多个promise实例当成一个promise实例,当这些实例的状态都发生改变时
//才会返回一个新的promise实例,才会执行then方法
Promise.all([
loadImg("http://i4.buimg.com/567571/df1ef0720bea6832.png"),
loadImg("https://ss1.baidu.com/9vo3dSag_xI4khGko9WTAnF6hhy/imgad/pic/item/6f061d950a7b0208b8265dea6ad9f2d3562cc8ca.jpg"),
loadImg("https://ss1.baidu.com/9vo3dSag_xI4khGko9WTAnF6hhy/imgad/pic/item/9f510fb30f2442a750999faed943ad4bd1130221.jpg")
]).then(showImgs);
}
十五、自定义接口:Symbol.iterator
,for…of遍历使用的就是Symbol.iterator
接口
Symbol.iterator
在对象中自定义itetator接口,然后使用for…of遍历
//数组
let arr = ['a', 'b', 'c'];
let map = arr[Symbol.iterator](); // 数组内部已经实现了Symbol.iterator接口
//arr[Symbol.iterator]会返回一个遍历的函数,再()一下执行这个函数,会返回一个对象
console.log( arr[Symbol.iterator] ) //ƒ values() { [native code] }
// // map.next()先返回第一个值,如果还有下一个值,则done为false
console.log( map.next() ) // {value: "a", done: false}
console.log( map.next() ) // {value: "b", done: false}
console.log( map.next() ) // {value: "c", done: false}
console.log( map.next() ) // {value: undefined, done: true}
//对象:自定义iterator接口,for...of循环使用的就是内部的Symbol.iterator接口遍历
let obj = {
start: [1,2,3],
end: [4,5,6]
[Symbol.iterator](){
let self = this,
arr = self.start.concat(self.end),
index = 0,
len = arr.length;
return {
next(){
if(index < len){
return {
value: arr[index++],
done: false
}
}else{
return {
value: arr[index++],
done: true
}
}
}
}
}
}
十六、异步编程:Generator函数、async是Gnerator函数的语法糖
Generator也是异步编程的一种解决方案。比promise更高级。
定义:function* (){}
关键字:yield
实践:
let tell=function* (){ // function加*
yield 'a';
yield 'b';
return 'c';
}
let k=tell(); //调用tell时遇到yield会停下来
//调用next时会执行第一个yield
console.log(k.next()); // Object {value: "a", done: false}
console.log(k.next()); // Object {value: "b", done: false}
console.log(k.next()); // Object {value: "c", done: true}
console.log(k.next()); // Object {value: "undefined", done: true}
//Generator返回的就是一个Iterator接口
让对象也可以遍历,Generator就是一个遍历器生成函数:
{
let obj={};
obj[Symbol.iterator]=function* (){
yield 1;
yield 2;
yield 3;
}
for(let value of obj){
console.log('value',value);
// value 1
// value 2
// value 3
}
}
状态机:
{
//状态机,只存在三种状态(A,B,C) (A->B->C->A->B....一直循环)
let state=function* (){
while(1){
yield 'A';
yield 'B';
yield 'C';
}
}
let status=state();
console.log(status.next()); // Object {value: "A", done: false}
console.log(status.next()); // Object {value: "B", done: false}
console.log(status.next()); // Object {value: "C", done: false}
console.log(status.next()); // Object {value: "A", done: false}
console.log(status.next()); // Object {value: "B", done: false}
}
async:
{
let state=async function (){
while(1){
await 'A';
await 'B';
await 'C';
}
}
let status=state();
console.log(status.next());
console.log(status.next());
console.log(status.next());
console.log(status.next());
console.log(status.next());
}
长轮询:
let ajax=function* (){
yield new Promise(function(resolve,reject){
setTimeout(function(){
resolve({code:0});
},2000);
});
}
let pull=function(){
let genertaor=ajax();
let step=genertaor.next();
step.value.then(function(d){ //这里的d就是上面的{code:0}
if(d.code!=0){
setTimeout(function(){
console.log('wait');
pull();
});
}else{
console.log(d);
}
})
}
pull();
十七、Decorator:修饰器 [作用于函数,修改行为,修改函数的行为]
需要babel导入下面的插件才能使用decorator:babel-plugin-transform-decorators-legacy
descripttor的使用:
//定义一个decorator函数,target是要修改的类,name是要修改的类的属性名称,
//descriptor是这个属性的描述,是一个对象
let readonly=function(target,name,descriptor){
console.log(descriptor);
// Object {writable: true, enumerable: false, configurable: true,value:function(){}}
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()); //2017-03-11
* target的使用: *
let typename=function(target,name,descriptor){
target.myname='hello'; //设置类的属性
}
@typename
class Test{
}
console.log('类修饰符',Test.myname); // 类修饰符 hello
// 第三方库修饰器的js库:core-decorators; npm install core-decorators
//这里之所以要用箭头函数,是因为要接收@log的参数
let log=(type)=>{
return function(target,name,descriptor){
console.log(descriptor);
// Object {writable: true, enumerable: false, configurable: true,value:function(){}}
let src_method=descriptor.value; //获取被修饰的方法
console.log(src_method);
// show(){
// console.info('ad is show');
// }
//修改方法的行为
descriptor.value=(...arg)=>{
src_method.apply(target,arg);
console.info(`log ${type}`);
}
}
}
class AD{
@log('show')
show(){
console.info('ad is show');
}
@log('click')
click(){
console.info('ad is click');
}
}
let ad=new AD();
ad.show();
ad.click();
十八、模块化
模块导入导出:
import {a,b,c} from '***'
⇒ export b; export a;exprot c;
import * as all from '***'
其中 all
为别名
import a from '***'
⇒ export default {name: 'a'}