ES6学习(二)基础命令
一、Let 和 const
作用域的概念:在es5之前是有两个作用域,一个是全局作用域,另外一个是函数作用域,在es6中就多了这样一个块作用域。在这里let 和 const 就是传说中的块作用域,它们的使用方法和 var 是一样的,只是作用是有区别的。
作用的区别有哪些呢,由下面的代码可见 i 是有报错的;
function test() { for (let i = 1; i < 3; i++) { console.log(i); } console.log(i); } test();
说明:
1)因为let 是块作用域,在for 的花括号内调用 i 是没有问题的, 但是若在 花括号外在调用 i 则找不到该 i ,因为这i 没有在外面声明,如果用var 是没有问题的 ;因此let 是一个块作用域 所以 i 脱离了块作用域,生命周期结束了,便会报错。由此可见es6 在语法强制使用了严格模式,严格模式就是变量没有生命就会报错!
2)另外一个需要注意的是,let 定义的变量不可以重复声明,否则会报错!
3)const 声明一个常量时必须要附一个值,const 常量的值后期是不可以更改的,否则会报错
function last() { const IP=111; const obj = { abc:111 } console.log(obj); obj.d = 222 } last();
4)const 对于数值常量 是不可以修改的,而对于 const 声明对象的时候是可以修改对象的元素,对象是引用类型,引用类型是对象的指针不可以改变,但是对象是可以变的。
二、解构赋值
数值解构赋值、对象解构赋值、字符串解构赋值、布尔值解构赋值、函数参数解构赋值、数值解构赋值。
1、数组解构赋值
{ let a,b,c; [a,b] = [1,2] console.log(a,b); }
输出:a=1 b=2
常见的数组解构赋值
{ let a,b,c; [a,b,...c] = [1,2,3,4,5,6]; console.log(a,b,c); }
输出:a=1 b=2 c=[3,4,5,6]
常见的对象解构赋值
{ let a,b; ({a,b} = {a:1, b:2}) console.log(a, b); }
输出: a=1 b=2
声明参数但是没有赋值
{ let a,b,c; [a,b,c] = [1,2]; console.log(a,b,c); }
输出:a=1 b=2 c 没有赋值为 undefind
使用场景(1)数据交换
{ let a = 1; let b = 2; [a,b] = [b,a]; console.log(a,b); }
输出:a=2 b=1
函数返回数组赋值
{ function fun() { return [1,2] } let a, b; [a,b] = fun(); console.log(a,b); }
输出: a=1 b=2
函数返回多个参数,可以只取部分参数
{ function fun() { return [1,2,3,4,5]; } let a,b,c; [a,,,b] = fun(); console.log(a,b); }
输出:a=1 b=4
函数返回数组参数,可以跳跃取,也可以使用 ...变量取所有参数
{ function fun() { return [1,2,3,4,5,6,7] } let a,b,c; [a,, ...b] = fun(); console.log(a, b); }
输出:a=1 b=[3,4,5,6,7]
对象的赋值,对象赋值,对象的左右都要是对象
{ let obj = {a:111, b:222}; let {a, b} = obj console.log(a, b); }
输出:a=111 b=222
对象赋值,默认值
{ let {a=1,b=2} = {a:100} console.log(a,b); }
输出:a=100 b=2
对象赋值要注意接收对象参数的格式
{ let data = { title:'this is a title', child:[{ id:123456, desc:'this is a desc' }] } let { title:setTitle, child:[{id:setId}] } = data; console.log(setTitle, setId); }
输出:setTitle='this is a title' setId=123456
三、正则扩展
构造函数的变化,正则方法的扩展,u修饰符,y修饰符,s修饰符
{ //ES5中正则的写法 let regex = new RegExp('xyz', 'i'); //2个参数 let regex2 = new RegExp(/xyz/i); //1个参数 console.log(regex.test('xyz123'), regex2.test('xyz123'));
//输出:true true
//ES6中的写法 let regex3 = new RegExp(/xyz/ig, 'i');//2个参数 console.log(regex3.flags);
//输出:i 说明:es6中的第二个参数会覆盖第一个参数的正则修饰符,flags 是输出正则修饰符 }
正则匹配 修饰符 g 和 y 区别
g 第一次匹配成功后 不会紧接着从第二个元素开始匹配,可以从任意位置去匹配
y 第调一有次匹配成功后 只会从紧接着的第二个开始匹配,匹配不成功就返回null
{ let s = 'bbb_bb_b'; let a1 = /b+/g; let a2 = /b+/y console.log('one', a1.exec(s), a2.exec(s)); console.log('two', a1.exec(s), a2.exec(s)); }
输出:one ["bbb", index: 0, input: "bbb_bb_b"] ["bbb", index: 0, input: "bbb_bb_b"]
two ["bb", index: 4, input: "bbb_bb_b"] null
console.log(a1.sticky, a2.sticky); //sticky 用于查看 变量是否使用了 y 模式,
a1 为 false 即没有使用y
a2 为 true 即使用了y修饰符
四、字符串扩展
字符串新增特性
在学习字符串这一块需要安装扩展库 执行代码如下
npm install babel-polyfill --save-dev
在项目中要引入ES7扩展库: import 'babel-polyfill';
1、针对unicode 编码解析
{ console.log('a', `\u0061`); console.log('s', `\u20bb7`); //字符编码大于FFFF 不能正常显示 console.log('s', `\u{20bb7}`); //这样写可以正常显示 }
显示结果:a a s ₻7 s 𠮷
{ let s = '𠮷'; console.log("length", s.length); }
结果:length 2 因为s 这个字符编码汉字FFFF, 的字节大于2字节的,所以这里就处理为4个字节了,每两个字节为 1个长度,所以这里 应该是2个长度,4个字节
2、查看一下ES5对UNICODE的编码处理
{ 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)); }
输出结果为: 0 � 1 � at0 55362 at1 57271
由此可见ES5对字符的编码处理并不是很完善
这里看一下ES6的处理结果
{ let s1 = '𠮷a'; console.log('length', s1.length); console.log('code0', s1.codePointAt(0)); //取第一个字符编码 console.log('code0', s1.codePointAt(0).toString(16)); console.log('code1', s1.codePointAt(1)); console.log('code2', s1.codePointAt(2)); }
结果:length 3 code0 134071 code0 20bb7 code1 57271 code2 97
由此可见 codePointAt 这个函数是可以取4个字节的编码, 当取 第一个字符编码的时候它会自动识别是个字节还是两个字节的字符。当取第二个字符编码的时候,它能够正常显示第二个字符的编码。
console.log(String.fromCharCode("0x20bb7")); //ES5中的取法 console.log(String.fromCodePoint("0x20bb7")); //ES6中的取法
输出结果:ஷ 𠮷 //可见ES6是多么完善呀
3、打印字符编码
let str = '\u{20bb7}abc'; for (let i = 0; i<str.length; i++) { console.log('es5', str[i]); } for (let code of str) { console.log('es6', code); }
打印结果:
es5 � es5 � es5 a es5 b es5 c
es6 𠮷 es6 a es6 b es6 c
由此可见,ES5中打印字节始终是安装两个字符去取的,而ES6可以通个关 let of 字符串遍历接口去打印,可以匹配得到4个字节的编码
4、查看字符串中的一些处理
{ //查看字符窜中是否包含某个字符 let str = 'string'; console.log('includes', str.includes('r')); //查看字符串中是以某某开始的 console.log('start', str.startsWith('str')); //查看字符串是以某某结束的 console.log('end', str.endsWith('ng')); //查看字符串重复复制 let str1 = 'abc'; console.log(str1.repeat(2)); }
输出结果:includes true start true end true abcabc
5、ES6中的模板字符串
{ let name = 'list'; let info = 'hello word'; let m = `this is a test ${name}, with ${info}`; console.log(m); }
输出结果:this is a test list, with hello word
6、字符串补白
{ //字符串补白 console.log('1'.padStart(2, '0')); //向前补白 console.log('1'.padEnd(2, '0'));//向后补白 }
输出结果:01 10 补白的作用于 选日期的格式, 第一参数说明:2 ,说明是要求需要两位,不够则在前补一个 0
7、标签模板的使用
{ let user = { name:'list', info: 'hello world' } console.log(abc`this is a ${user.name} you will can look ${user.info}`);; function abc( s, v1, v2) { console.log(s, v1, v2); return s+v1+v2 } }
输出结果:this is a , you will can look , list hello world
作用:1、处理多语言,通过处理参数,返回不同的结果。2、防止数据攻击
8、String.row的使用 对斜杠 进行一个转义
{ console.log(String.raw`ni hao \n ${1+2}`); console.log(`ni hao \n${1+2}`); }
输出结果:
ni hao \n 3
ni hao
3
五、数值扩展
{ //多进制的表示方法 console.log(0b111110111); //输出结果: 503 console.log(0o767);//输出结果: 503 //是否有尽 console.log('15', Number.isFinite(15)); // 输出结果 15 true console.log('NaN', Number.isFinite(NaN));// 输出结果 NaN false console.log('1/0', Number.isFinite('TRUE'/0));// 输出结果 1/0 false //判断是否是一个数 console.log('NaN', Number.isNaN(NaN));//输出结果:NaN true console.log('0', Number.isNaN(0)); //输出结果:0 false //是否是整数 console.log('25', Number.isInteger(25));//输出结果:25 TRUE console.log('25.0', Number.isInteger(25.0));//输出结果:25.0 TRUE console.log('25.1', Number.isInteger(25.1));//输出结果:25.1 FALSE console.log('string', Number.isInteger('25.1ABC'));//输出结果:string FALSE //表示数的最大的一个上线 console.log(Number.MAX_SAFE_INTEGER); //输出结果:9007199254740991 //表示数的最小的下线 console.log(Number.MIN_SAFE_INTEGER);//输出结果:-9007199254740991 //验证数是否送一个安全的数,一定要是一个数 console.log('10', Number.isSafeInteger(10));//输出结果: 10 TRUE console.log('a', Number.isSafeInteger('a'));//输出结果: a false //小数取整 console.log(4.1, Math.trunc(4.1));//输出结果: 4.1 4 console.log(4.9, Math.trunc(4.9));//输出结果: 4.9 9 //判断是整数,负数 还是 O,字符串可以转为 console.log('-5', Math.sign(-5));//输出结果: -5 -1 console.log('5', Math.sign(5));//输出结果: 5 1 console.log('0', Math.sign(0));//输出结果: 0 0 console.log('50', Math.sign('50'));//输出结果: 50 1 console.log('fun', Math.sign('fun'));//输出结果: fun NaN //立方根 console.log('-1', Math.cbrt(-1));//输出结果: -1 -1 console.log('8', Math.cbrt(8));//输出结果: 8 2 }
输出结果:
六、数组扩展
{ let arr = Array.of( 1,2,3,4,5 ); console.log('arr=', arr); //输出结果:arr= (5) [1, 2, 3, 4, 5] let mepty = Array.of(); console.log('mepty', mepty);//输出结果:mepty [] let array = Array.of(1,2,3,4,5,67,7); array.forEach(function (item) { console.log(item);//输出结果:打印数组元素 }) let p = document.querySelectorAll('p'); let pArr = Array.from(p); pArr.forEach(function (item) { console.log(item.textContent);//输出结果:打印数组元素 }) //映射处理 console.log(Array.from([1,2,3], function (item) { return item*2 })); //打印:2,4,6 //全部转为 7 console.log('fill-7', [1,'a', undefined].fill(7));//全部替换为:fill-7 (3) [7, 7, 7] //从第一位开始替换到第三位 console.log('fill,pos',['a', 'b', 'c'].fill(7,1,3));//输出结果;fill,pos (3) ["a", 7, 7] //打印数组的 KEYs for ( let index of [1,'c', 'v'].keys() ) { console.log('keys', index); } //打印数组的 values for ( let value of [1,'c', 'v'].values() ) { console.log('keys', value); } }
七、set-map 数据结构
set的使用、weakset的用法、map的用法、weakmap的用法
{ let list = new Set(); list.add(5); list.add(7); console.log('size', list.size);//查看长度 //输出 size 2 } { 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);//打印数据 //输出的是 lis t{1,2} 可见set具有去重的效果 } { let arr = [1,2,3,1,2,'1','2']; let list = new Set(arr); console.log('unique', list); //unique {1, 2, 3, "1", "2"}可见set具有去重的效果 并且不会自动转义 } { 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 {"delete", "clear", "has"} list.clear(); console.log('list', list); //list {} } { let arr = ['add', 'delete', 'clear', 'has']; let list = new Set(arr); for( let key of list.keys() ) { console.log('key', key); } for( let val of list.values() ) { console.log('defaultValue', val); } for( let list of list ) { console.log('list', list); } //效果雷同 for( let [key, val] of list.entries() ) { console.log('entries', key, val); } //entries add add //entries delete delete //entries clear clear //entries has has list.forEach(function (item) { console.log(item); }); //add //delete //clear //has }
Weaklist的使用
{ //只能放对象元素 不能垃圾回收 不能遍历 let weaklist = new WeakSet(); let arg = {}; weaklist.add(arg); console.log(weaklist); }
Map的使用
{ let map = new Map(); let arr = ['123']; map.set(arr,456); console.log('map', map, map.get(arr)); //map Map {_c: Map(1)} 456 } { let map = new Map([['a', 1111], ['b', 2222]]); console.log('map', map); //Map(2) {"a" => 1111, "b" => 2222} console.log('size', map.size); //size 2 console.log('delete', map.delete('a'), map); console.log('clear', map.clear(), map); //delete true Map {_c: Map(1)} //clear undefined Map {_c: Map(0)} }
weakmap的使用
{ //key值必须是对象,没有clear 也不能遍历 let weakmap = new WeakMap(); let o = {}; weakmap.set(o, 123) console.log(weakmap.get(o)); }
数据结构
Map 和 Array 的对比
{ //数据结构的横向对比,增删改查 let map = new Map(); let array = []; //增 map.set('t', 1); array.push({t:1}); console.log('map-array', map, array); //查 let map_exist = map.has('t'); let array_exist = array.find(item => item.t); console.log('map-array-exist', map_exist, array_exist); //map-array-exist true {t: 1} //map 返回 true ,而array 返回数组元素 //改 map.set('t', 2); array.forEach(item=>item.t?item.t=2:''); //删 map.delete('t'); let index = array.findIndex(item=>item.t) array.splice(index, 1); console.info('map-array-empty', map, array) }
Set 和 Array 的对比
{ //Set 和 Array 的对比 let set = new Set(); let array = []; //增 set.add({t:1}); array.push({t:1}); console.info('set-array', set, array); //查 let set_exist = set.has({t:1}); let array_exist = array.find(item => item.t); console.info('set-array', set_exist, array_exist); //改 set.forEach(item => item.t?item.t=2:''); array.forEach(item=>item.t?item.t=2:''); console.log('set-array-update', set, array); //删 set.forEach(item=>item.t?set.delete(item):''); let index = array.findIndex(item=>item.t); array.splice(index, 1); console.info('set-array-empty', set, array); }
Map 和 Object 的对比
Set 和 Object的对比
{ let item = {t:1}; // set map obj 对比 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({ map_exist:map.has('t'), set_exist:set.has(item), obj_exist:'t' in obj }); //{map_exist: true, set_exist: true, obj_exist: true} //改 map.set('t', 2); item.t = 2; obj['t'] = 2; console.log('map-set-obj-modify', map, set, obj); //删 map.delete('t'); set.delete(item); delete obj['t']; console.log('map-set-obj-delete', map, set, obj); }
八、Proxy 和 Reflect
proxy 和 reflect的概念
proxy 和 reflect 的适用场景
{ let obj = { time: '2018-04-01', name:'app', _r:123 }; let monitor = new Proxy(obj, { //拦截对象属性的读取 get(target, key){ return target[key].replace('2018', '2019'); }, //拦截对象设置属性 set(target, key, value){ if (key == 'name') { return target[key] = value; } else { return target[key] } }, //拦截key in object操作 has(target, key) { if ( key === 'name' ) { return monitor[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 2019-04-01 monitor.time = '2018'; console.log('set', monitor.time); monitor.name = '1234566'; console.log('get', monitor.name); //get 1234566 console.log('has', 'name' in monitor, 'time' in monitor);//has true false delete monitor.time; console.log('deletee', monitor);//{time: "2018-04-01", name: "1234566", _r: 123} delete monitor._r; console.log('deletee', monitor);//{time: "2018-04-01", name: "1234566"} console.log('ownKeys', Object.keys(monitor));//["name", "_r"] }
reflect的使用
{ let obj = { time: '2018-04-01', name:'app', _r:123 }; console.log('reflect get', Reflect.get(obj, 'time')); //reflect get 2018-04-01 Reflect.set(obj, 'name', 'nihaoya'); console.log('obj', obj);//{time: "2018-04-01", name: "nihaoya", _r: 123} console.log('has', Reflect.has(obj, 'name'));//has true }
九、类
类的基本概念
基本语法 类的继承 静态方法
静态属性 getter setter
{ //基本定义和生成实例 class Parent { constructor( name = 'nihao') { this.name = name; } } let v_parent = new Parent('v'); console.log('构造函数和实例', v_parent);//构造函数和实例 Parent {name: "v"} }
继承
{ //继承 class Parent{ constructor(name = 'nihao') { this.name = name; } } class Child extends Parent { } console.log('继承', new Child());//继承 Child {name: "nihao"} }
继承传递参数
{ //继承传递参数 class Parent{ constructor(name = 'nihao') { this.name = name; } } class Child extends Parent { constructor(name = 'child') { super(name); } } console.log('继承传递参数', new Child());//继承传递参数 _Child {name: "child"} console.log('继承传递参数', new Child('lcc'));//继承传递参数 _Child {name: "lcc"} }
getter setter | 静态方法 | 静态属性
{ //getter setter class Parent{ constructor(name = 'nihao') { this.name = name; } get longName() { return 'lcc' + this.name; } set longName(value) { this.name = value; } } let v = new Parent(); console.log('getter', v.longName); //getter lccnihao v.longName = 'hello'; console.log('setter', v.longName); //setter lcchello } { //静态方法 用类调用,而不是用类的实例调用 class Parent{ constructor(name = 'nihao') { this.name = name; } static tell() { console.log('tell'); } } Parent.tell(); } { //静态属性 class Parent{ constructor(name = 'nihao') { this.name = name; } } Parent.type = 'test'; console.log('静态属性', Parent.type); //静态属性 test }
十、Promise
Promise是解决异步操作顺序应用的,什么是异步,Promise的作用,Promise 的基本用法
如下输出的顺序是 执行 然后是 timeout1 如果代码很多是很难知道哪一个先执行的,因此引入Promise
{ //基本定义 let ajax = function (callback) { console.log('执行'); setTimeout( function () { callback&&callback.call(); }, 1000); } ajax(function () { console.log('timeout1'); }) }
{ let ajax = function () { console.log('执行2'); return new Promise(function (resolve, reject) { setTimeout(function () { resolve(); }, 1000) }) } ajax().then(function () { console.log('promist', 'timeout2'); //promist timeout2 }) } { let ajax = function () { console.log('执行3'); return new Promise(function (resolve, reject) { setTimeout(function () { resolve(); }, 1000) }) } ajax().then(function () { return new Promise(function ( resolve, reject ) { setTimeout(function () { resolve() }, 2000) }).then(function () { console.log('timeout3'); }) }) }
Cache的使用
{ 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 (err) { console.log('catch', err); }) ajax(3).then(function () { console.log('log', 3); }).catch(function (err) { console.log('catch', err); }) }
十一、Lterator 和 for ... of 循环
什么是lterator 接口
lterator 的基本用法
for ... of
{ let arr = ['hello', 'world']; let map = arr[Symbol.iterator](); console.log(map.next()); console.log(map.next()); console.log(map.next()); //{value: "hello", done: false} //{value: "world", done: false} //{value: undefined, done: true} } { let obj = { start:[1,3,2], end:[7,9,8], [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); } }
{ let arr = ['hello', 'world']; for (let key of arr) { console.log('value', key); } }
十二、模块化
基本概念, ES6的模块语法
Export 的导出 Import 的导入
未完待续......