前言
大概是半年前学的,当时放到CSDN上的,现在搬到自己博客上
这是我学习ES6的笔记,语言偏向口语化,主要是个人觉得这样会比较亲切…
由于是学习笔记,内容可能会有不够详实,存在瑕疵等诸多问题,欢迎大家在评论区批评指正
希望接下来的内容能够在大家学习ES6的过程中给予一点帮助
ES的定义 即ECMAScript,脚本语言的规范
其中的ECMA的全称是全称:European computer manufacturers association欧洲计算机制造联合会,后改名为ECMA国际 。
ES新特性指的是JavaScript的新特性.
为什么学ES 概括为—-更方便更高能
接下来进入正题:
1.let声明 let a = 233,翻译就是让a等于233,简直语义化啊!
使用方式(就是变量声明啦)
1 2 3 4 let a;let b, c;let d = 100 ;let e = 666 , f = 'hhh' , g = [];
特性
变量不能重复声明,否则报错 (没错,var是可以重复的)
增加块级作用域 (ES5中有三种作用域:全局、函数、严格模式中的eval)C/C++转过来的简直感动
举个栗子:
1 2 3 4 { let a = '我在一个块里面' ; console .log('这是第1个:' + a); }
上图的运行结果:
1 2 3 4 { let a = '我在一个块里面' ; } console .log('这是第2个:' + a);
上图的运行结果 补充一点,if、else、while、for等也可以形成块级作用域
取消变量提升
1 2 3 4 console .log('我是' + Var);console .log('我是' + Let);var Var = 'var' ;let Let = 'let' ;
上图运行结果: (undefined是声明提升但是赋值不提升导致的)
依旧有作用域链2.const声明
就是常量啦
使用方式
1 2 const A = "必须要初始化(赋值)" ;
特性
一定要赋初始值
赋值完成后不可修改(毕竟声明的是常量)
也有块级作用域
对于用const声明的数组和对象,可以修改其元素
3.新特性:解构赋值 字面意思就是把结构拆解然后赋值? 关于这个东西呢直接举例子比较好数组的解构赋值
1 2 3 const ARRAY = [1 ,2 ,3 ,4 ];let array = [a,b,c,d] = ARRAY;console .log(a,b,c,d);
上图运行结果: awsl!!!!怎么样,是不是爽的不要不要的?!对象的解构赋值
1 2 3 4 5 6 7 8 9 10 const MyInfo = { name :'Serio' , ablity :'TouchFish' , TouchFish :function ( ) { console .log('没人比我更懂摸鱼' ); } }; let InfoOfMine = {name,ablity,TouchFish} = MyInfo;console .log(name,ablity);TouchFish();
上图运行结果: 其中对 对象的方法 进行解构是最常用的,为了偷懒 方便 需要注意的是,各个元素的名字需要一致,否则报错。
4.新特性:模板字符串 孔丙己便涨红了脸,额上的青筋条条绽出,争辩道,“ES5不能……换行!……ES6的事,还用换行吗? ”接连便是难懂的话,什么“作用域链”,什么“闭包”之类,引得众人都哄笑起来:店内外充满了快活的空气
使用方式
新旧对比
1 2 3 4 5 6 let str = '换行昂昂昂\ 要加上斜杠,或者加号连接' + '不然会报错的' ; let strES6 = `没错,现在我们用\`(反引号,就是键盘上和~一个位置那个) 表示字符串惹~ 换行很方便的~~~` ;
特性
可以直接换行了
可以直接拼接变量
(配合高贵的${})
1 2 3 let a = 3 ;let str = `我要给这篇文章一个${a} 连` ;console .log(str);
上图运行结果 感谢各位读者,感谢一路走来给予我支持和帮助的老师和前辈….阿巴阿巴(手动狗头)
5.新特性:对象属性声明简化 使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 let name = 'Serio' , level = '蒟蒻' ; function showAbility ( ) { console .log('BUG + 1' ); } const FEIWU = { name, level, showAbility, checkMoney ( ) { console .log(`果然没钱` ); } } FEIWU.showAbility(); FEIWU.checkMoney();
上图运行结果:
特性 似乎…没啥特性
6.新特性:箭头函数 “你知道吗,箭头函数的语法糖,有四种写法”
使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let fn = (a, b )=> { console .log(a + b); } fn('啊' ,'是箭头函数' ); fn = a => { console .log(`笑死我${a} ` ); } fn(2333 ); fn = (a,b )=> console .log(a + b); fn(1 ,1 ); fn = (a )=> a + 1 ; console .log(fn(9 ));
上图运行结果
特性
静态this 对于function声明的函数,谁调用this就指向谁; 但是对于箭头函数来说,其this永远指向函数声明时的作用域下的this,并且不能被call,bind等方法改变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 let whereIsThis1 = function ( ) { console .log("1普通函数" + this ); } let whereIsThis2 = ()=> { console .log("2箭头函数" + this ); } const WhereRU = { whereIsThis1, whereIsThis2 } WhereRU.whereIsThis1(); WhereRU.whereIsThis2();
上图运行结果 所以箭头函数适用于与this无关的情况
不能实例化对象(就是不能作为构造函数,也就是不能new)
没有arguments了(悲伤)
多种省略形式(没错就是开头的几种形式)
7.函数参数默认值 说实话看到这个新特性的时候我第一也是唯一的反应就是———— 原来以前没有吗??? 使用方式
1 2 3 4 5 6 function calc (a,b,c = 220 ) { console .log(a + b + c); }; calc(100 ,200 ); calc(100 ,200 ,1014 );
上图运行结果
8.rest参数 “arguments的离去,是rest的要求,还是es6的不挽留” (其实arguments不仅还能用,还挺好用的)使用方法
1 2 3 4 5 function UltramanBros (a,b,...args ) { console .log(a,b,args); } show("佐菲" ,"初代" ,"赛文" ,"艾斯" ,"泰罗" ,"雷欧" );
上图运行结果 …是扩展运算符 ,能将数组展开成参数序列, 所以传入…args相当于传入了n个参数, 超出的四个参数依次对应,然后存入args中
9.Symbol类型 JS的第七种数据类型(话说前六种是啥来着) 这次我们先说特性特性
值唯一,解决了命名冲突问题
不能与其他类型的数据进行运算
Symbol类的对象不能用加强for循环(for in),但是可以用Reflect.ownKeys
我对Symbol的理解: 就是根据你传入的内容产生一个(伪)随机的、不重复的值,感觉原理就是哈希表(散列表) (如果没错的话,那么理解哈希表会帮助理解Symbol)
使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 let s1_1 = Symbol ('第一类' ); let s1_2 = Symbol ('第一类' ); console .log(s1_1 === s1_2); console .log('第一类声明的索引' + Symbol .keyFor(s1_1)); let s2_1 = Symbol .for('第二类' ); let s2_2 = Symbol .for('第二类' ); console .log(s2_1 === s2_2); console .log('第二类声明的索引' + Symbol .keyFor(s2_1));
上图运行结果 第一类声明没有“记录机制”,同样的内容是不同的值,而且不能根据值反过来找索引
第二类则有“记录机制”,与第一类相反
运用 有什么用? 参考一下哈希表,至少能够用来安全、随机、可查询地在数组中存储数据….(啊,我也不知道)(哦哦我是蒟蒻,所以我也不该知道—-骄傲!)
Symbol内置值 这个对于我来说有点晦涩,而且看上去用处不是很大, 这里先暂时跳过,等我学懂了再补上….
10.迭代器 ES6中新增for-of 遍历 迭代器是用来做什么的呢?就是用来遍历的,为不同的数据结构提供了同样的访问方式:只要某种数据结构中具备iterator的接口,就可以使用迭代器遍历
首先我们来说一下两种迭代遍历: for-in和 for-of
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const SZ3L = ['woc' ,'NB' ,'666' ]; for (var i = 0 ; i < SZ3L.length; i ++){ (function (a ) { console .log('普通for循环' ,a); })(i); } for (let i in SZ3L){ console .log('for-in循环:' + i); } for (let i of SZ3L){ console .log('for-of循环:' + i); }
上图运行结果 可以看到, for-in是遍历数组的下标(键), for-of则是遍历数组的值
浅析原理 (我是废物,说不清楚) (还得再研究一下,主要还是Symbol没学懂) 迭代器工作过程简单概括为以下3步: 1.创建一个指针对象,指向当前数据结构起始位置 2.调用对象的next方法 ,指向下一个成员并返回一个包括value和done属性的对象(注意是next方法返回对象) , 重复这个过程,直到指向最后一个成员 3.修改done属性为true,遍历完成,停止调用next
1 2 3 4 5 6 let iterator = SZ3L[Symbol .iterator]();console .log(iterator.next());console .log(iterator.next());console .log(iterator.next());console .log(iterator.next());
上图运行结果 其中,done属性是表示是否遍历完成,当访问到最后一个数据 时,done的属性从false变为true,迭代器停止遍历
现在来手写一个迭代器 经过多年的研究之后,我为各位读者量身定义了reader对象, 并手写一个迭代器遍历appearance属性数组
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 const reader = { salary :"月薪10k起步" , appearance :[ '女美男帅' , '墨发雪肌' , '壮得一批' ], [Symbol .iterator](){ let index = 0 ; return { next :()=> { if (index < this .appearance.length){ index ++; return {value :this .appearance[index], done :false }; }else { return {value :undefined , done :true }; } } } } } for (let i of reader.appearance){ console .log(i); }
上图运行结果
11.生成器 生成器是一个特殊的函数,用于更好地解决异步编程(虽然还是已经被更更更好的方法替代了,不过还是得学) 使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function * myFriends ( ) { console .log('后端学习打卡时长排名的人数显示器' ); yield '阿波' ; console .log('明明是嵌入式的实验室却专攻后端' ); yield '陈大爷' ; console .log('算法很强的后端并且还在学Unity做游戏' ); yield '豪老板' ; } let iterator = myFriends(); console .log(iterator.next()); console .log(iterator.next()); console .log(iterator.next()); console .log(iterator.next());
上图运行结果 (为什么都是后端?巧合吧)解析 yield相当于一条有名字的分界线 ,我们可以通过迭代器的next方法执行每一部分的内容
第一次调用next时,执行第一条分界线以上的内容 第二次调用next时,执行第二条以上,第一条以下的内容 以此类推…
使用方式2 生成器 和 next方法 都可以传参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function * gen (a ) { console .log('这是分界线1里的' + a); let one = yield '分界线1' ; console .log('分界线1的返回值' + one); let two = yield '分界线2' ; console .log('分界线2的返回值' + two); let three = yield '分界线3' ; } let iterator = gen('一个参数' );console .log(iterator.next()); console .log(iterator.next(233 ));console .log(iterator.next());console .log(iterator.next());
上图运行结果 生成器gen传参和普通方法一样
next方法的参数,是作为上一条分界线的返回值
比如,第二次调用next,其参数作为 yield ‘分界线1’ 的返回值 要是没有传递参数,那么yield的返回值为undefined
特性
关键字function与函数名称中间有个 *
使用了yield表达式
直接调用会返回一个迭代器对象
运用 说是优化异步编程的,那么我们来看看没有生成器的时候存在的问题:回调地狱
回调函数 :将一个函数作为参数传递,但是这个函数不会立刻执行,而是会等待某个条件触发才执行回调地狱 :异步明明是没有固定执行顺序的,那么如果我们偏要它有顺序,就会出现下图这样的结构
1 2 3 4 5 6 7 8 9 10 setTimeout (function ( ) { console .log('3s时执行第一层' ); setTimeout (function ( ) { console .log('5s时执行第二层' ); setTimeout (function ( ) { console .log('6s时执行第三层' ); }, 1000 ) }, 2000 ) }, 3000 )
如果代码量少还好受,要是多了就不好说了 这种回调函数的嵌套就是回调地狱 所以我们可以通过一些方式改善这种情况,比如用生成器:
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 function one ( ) { setTimeout (()=> { console .log('3s时执行第一层' ); g.next(); },3000 ) } function two ( ) { setTimeout (()=> { console .log('5s时执行第二层' ); g.next(); },1000 ) } function three ( ) { setTimeout (()=> { console .log('6s时执行第三层' ); g.next(); },1000 ) } function * gen ( ) { yield one(); yield two(); yield three(); } let g = gen();g.next();
上图运行结果 其实上面还有个一个点可以提一下,就是let明明没有了提升,g却依旧能被上面的函数访问, 和别人讨论了一下觉得应该是由于function声明的时候函数体不会展开,此时g也就没有被访问;等到g.next执行,one,two,three依次执行的时候,才依次展开,此时就可以通过作用域链向上访问到g从而能再次调用g.next…阿巴阿巴(反正大概就是那个意思)
12.Promise promise是一个构造函数,可以用来封装异步操作,并获取到其成功和失败的结果然后据此作出反应使用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 const p = new Promise (function (resolve, reject ) { setTimeout (function ( ) { let data1 = '成功了!' ; resolve(data1); let data2 = '失败了!' ; reject(data2); },1000 ); }); p.then(function (value ) { console .log('这是成功了:' + value); }, function (reason ) { console .log('这是失败了:' + reason); })
上图运行结果 从结果来看,似乎在遇到resolve方法之后就结束了而不是继续往下执行 (Promise的状态一旦变化,就不会再改变了) 另外介绍一下catch方法
1 2 3 4 p.catch(function (reason ) { console .log('这也是失败了,不过语法糖比较甜对吧' + reason); })
运用 首先我们来回忆一下原生JS的AJAX 现在准备一个这样的JSON文件
然后(这里是同一目录下)写AJAX
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 httpRequest = new XMLHttpRequest(); if (!httpRequest) { alert("创建请求失败" ); } httpRequest.open("GET" , "./JSONtest.json" ); httpRequest.send(); httpRequest.onreadystatechange = function ( ) { if (httpRequest.readyState === 4 ) { if (httpRequest.status === 200 ) { var data = JSON .parse(httpRequest.responseText); console .log('AJAX' + data['key' ]); } else { console .error('请求失败' ); } } }
上图运行结果
接下来我们来演示一次传说中的封装 !!!
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 const P = new Promise ((resolve, reject )=> { const xhr = new XMLHttpRequest(); if (!xhr){ console .error('创建请求失败' ); } xhr.open("GET" ,"./JSONtest.json" ); xhr.send(); xhr.onreadystatechange = function ( ) { if (xhr.readyState === 4 ){ if (xhr.status === 200 ){ let data = JSON .parse(xhr.responseText)['key' ]; resolve(data); }else { reject(xhr.status); } } } } ); P.then(function (data ) { console .log('你的AJAX生了,是个' + data); },function (reason ) { console .log('你的AJAX是个男的' + reason); })
“就这?就这?这不就是把ajax装进Promise里面吗?我人傻了” “大家懂的都懂,这种博主老水怪了 ”上图运行结果
特性 (写这个的时候有点困,估计很多问题,后面再改改,现在大家看看就行)
Promise.then方法的返回值:不写return默认返回一个Promise对象(是被处理之前的Promise)
第一种:内部 回调函数 返回非Promise类型
1 2 3 4 5 6 7 8 9 10 11 const P = new Promise ((resolve,reject ) => { resolve('abab' ); }); const result = P.then(value => { console .log(value); return '我是第一种返回值(非Promise类型)' ; },reason => { }) console .log(result);
上图运行结果第二种:内部 回调函数 返回Promise类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const P = new Promise ((resolve,reject ) => { resolve('abab' ); }); const result = P.then(value => { console .log(value); return new Promise ((resolve, reject ) => { reject('第二种类型:最内部promise的状态决定最终的状态' ) }) },reason => { }) console .log(result);
上图运行结果 第三种:throw
1 2 3 4 5 6 7 8 9 10 11 12 13 const P = new Promise ((resolve,reject ) => { resolve('abab' ); }); const result = P.then(value => { console .log(value); return new Promise ((resolve, reject ) => { reject('第三种类型:抛出错误' ); }) },reason => { }) console .log(result);
上图运行结果 通过观察以上三种情况,我们发现:这形成了一个链…也就避免了回调地狱的情况……..
(今天写不动了…好困…团队的人还在商量着今晚去吃自助的事情…又困又饿…以后找个时间一定把这里补起来)
(时隔几天,考完了高数….promise剩下的内容以后补充)
13.Set对象 那个橘子味的夏天,少年回忆起了蝉鸣和STL类库…
特性
拥有iterator接口,可以使用迭代器和扩展运算符(…)
类似于数组,但是具有唯一性 ,即元素不重复
属性/方法
size 返回元素个数
add 增加一个新元素,返回增加元素后的集合
delete 删除元素,返回一个布尔值
has 查询是否包含某个元素,返回一个布尔值
clear 清空,没有返回值(或者说返回undefined)
代码实例 先单独说一下add
1 2 3 4 5 6 7 8 9 10 let s = new Set ();let s2 = new Set (['甲' , '乙' , '丙' , '乙' , '甲' ]);console .log(s2);s2.add('one' ,'two' ); s2.add(['a' ,'b' ]); s2.add(...['1' ,'2' ]); console .log(s2);
上图运行结果 都没什么特别的, 需要提一下的就是如果传入多个参数,只有第一个有效(不仅局限于add,delete,has等也是如此)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 let s = new Set ();let s2 = new Set (['甲' , '乙' , '丙' , '乙' , '甲' ]);s2.add('one' ,'two' ); s2.add(['a' ,'b' ]); s2.add(...['1' ,'2' ]); console .log(s2.delete('甲' ,'乙' ));console .log(s2.delete('不存在的元素' ));console .log(s2.add('520' ));console .log(s2.size);console .log(s2.has('丙' ,'666' ));console .log(s2.clear(),s2);
上图运行结果运用 1.数组去重
1 2 3 4 let arr = [1 ,2 ,3 ,3 ,2 ,1 ];let s = [...new Set (arr)];console .log(s);
上图运行结果2.求交集 这里顺便介绍:
14.filter 过滤器,遍历每个元素 进行筛选代码实例
1 2 3 4 5 6 7 8 9 10 11 let arr = [1 ,2 ,3 ,2 ,1 ];let arr2 = arr.filter((value,key,arr )=> { console .log('这是value' ,value); console .log('这是key' ,key); console .log('这是arr' ,arr); return value > 2 ? true : false ; }) console .log('这是过滤之后的结果' ,arr2);
数组长度是5,函数执行了5次遍历了每个元素,筛选出了大于2元素
好了我们继续看我们的求交集
1 2 3 4 5 6 7 8 9 let arr = [1 ,2 ,3 ,4 ,3 ,2 ,1 ];let arr2 = [1 ,2 ,1 ];let s2 = new Set (arr2);let s1 = new Set (arr.filter((value )=> { return s2.has(value) ? true : false ; })); console .log(s1);
3.求并集 这个就没啥说的了
1 2 3 4 let arr = [1 ,2 ,3 ];let arr2 = [3 ,4 ,5 ];let s = new Set ([...arr,...arr2]);console .log(s);
4.求补集 其实也就和求交集一个意思
1 2 3 4 5 6 7 8 9 let arr = [1 ,2 ,3 ,4 ];let arr2 = [1 ];let s2 = new Set (arr2);let s = new Set (arr.filter((value )=> { return s2.has(value) ? false : true ; })); console .log(s);
不过这里有八十岁老爷爷看了都说牛逼的简化:
1 2 3 4 5 6 7 8 let arr = [1 ,2 ,3 ,4 ];let arr2 = [1 ];let s = new Set (arr.filter((value )=> { return !new Set (arr2).has(value); })); console .log(s);
15.map对象 其实就是键值对特性
又是一个自带iterator接口的
属性/方法
size 长度
set 添加元素
has 查询是否存在
clear 清空
get 通过键传入值
delete 通过键删除元素
代码实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 let m = new Map ();m.set(233 ,'键233的值' ); let obj = {name :'一个对象' };m.set(obj,'键对象的值' ); console .log('m.get(233):' , m.get(233 ));console .log('m.get(obj):' , m.get(obj));console .log('m.has(obj)' ,m.has(obj));console .log('m.size:' ,m.size);console .log('clear之前:' ,m);m.clear(); console .log('clear之后:' ,m);
16.class类 先回顾一下构造函数实例化对象 :
1 2 3 4 5 6 7 8 9 10 11 12 function Person1 (name, age ) { this .name = name; this .age = age; } Person1.prototype.speak = function ( ) { console .log('I\'m the ' + this .name +' DEEP! DARK! FANTASY♂!' ); } let somebody1 = new Person1('黑暗之王' ,18 );somebody1.speak();
class类实例化对象 (javar狂喜)
1 2 3 4 5 6 7 8 9 10 11 12 13 class Person2 { constructor (name, age ) { this .name = name; this .age = age; } speak ( ) { console .log('我是' + this .name + ',我是不朽的' ); } } let somebody2 = new Person2('玛尔加尼斯' ,5 );somebody2.speak();
static静态 不论新旧,都有这样一手操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Coder1 { } function Coder2 ( ) { } Coder1.name = '知鑫' ; Coder2.name = '雨溪' ; let coder1 = new Coder1();let coder2 = new Coder2();console .log('红尘作伴,代码潇潇洒洒~' );console .log(coder1.name,coder2.name);
快快乐乐,昂第佛爱德~ 通过上述方式添加的成员,只属于构造函数而不属于实例化对象.
上述写法相当于(static只能在class类里面合法)
1 2 3 4 5 class Coder3 { static name = '日娃' ; } let coder3 = new Coder3();console .log('无名英雄,程序员:' + coder3.name);
无名英雄的名字当然是undefined啊! 继承 又让我们先回顾构造函数如何继承吧(JS高级的原型链…说实话我也快忘完了)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function Win10 (info, bugs ) { this .info = info; this .bugs = bugs; } function Win11 (info, bugs, moreBugs ) { Win10.call(this ,info,bugs); this .moreBugs = moreBugs; } Win11.prototype = new Win10; Win11.prototype.constructor = Win11; Win11.prototype.start = function ( ) { console .log('绿屏了' ); } let newSystem = new Win11('最后一代?从来没说过' ,'挺多' ,'更多了' );console .log(newSystem);newSystem.start();
啥?为啥方法要写到prototype里面而不是直接写到对象里面?(上一节static静态 才说了
class继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Win10 { constructor (info,bugs ) { this .info = info; this .bugs = bugs; } } class Win11 extends Win10 { constructor (info,bugs,moreBugs ) { super (info,bugs); moreBugs = moreBugs; } start ( ) { console .log('绿屏了' ); } } let mySystem = new Win11('谁说win10是最后一代了?' ,'有bug' ,'更多bug!' );mySystem.start(); console .log('mySystem:' ,mySystem);
虽然看上去和JAVA差不多了,但是实际上还是原型链的封装 子类对父类方法的重写也一样,其实只是原型链的知识…
17.get与set 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Coder { get whyWeLive (){ console .log('为了吃饭' ); return false ; } set whyWeLive (dream ){ console .log('为了理想' ); return true ; } } let us = new Coder();let ans = us.whyWeLive; console .log(ans);us.whyWeLive = '为更多的人创造更好的世界' ;
注意whyWeLive是属性不是方法, get修饰是指,在该属性被访问的时候,调用后面的函数 set修饰是指,在该属性被修改的时候,调用后面的函数
人生来不是为了吃饭,我们还有理想
18.数值扩展 感觉这部分也没什么好说的,了解一下就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 console .log('0.1 + 0.2 === 0.3' , 0.1 + 0.2 === 0.3 ); function equal (a, b ) { return Math .abs(a - b) < Number .EPSILON ? true : false ; } console .log('equal(0.1 + 0.2, 0.3):' , equal(0.1 + 0.2 , 0.3 )); let a = 20 ;let b = 0b10100 ;let c = 0o24 ;let d = 0x14 ;console .log('十进制' , a, '二进制' , b, '八进制' , c, '十六进制' , d);console .log('Number.isNaN(100 / 0):' , Number .isNaN(100 / 0 ));console .log('Number.isFinite(100 / 0):' , Number .isFinite(100 / 0 ));console .log('Number.isInteger(2.3):' , Number .isInteger(2.3 ));console .log('Number.parseInt(\'2333ababa66\'):' , Number .parseInt('2333ababa66' ));console .log('Number.parseFloat(\'1.7321abcd\'):' , Number .parseFloat('1.7321abcd' ));console .log('Math.trunc(4.33):' , Math .trunc(4.33 ),'Number.parseInt(\'4.33\'):' , Number .parseInt(4.33 ));console .log('Math.sign(0):' ,Math .sign(0 ),'Math.sign(-666):' ,Math .sign(-666 ));
唯一需要注意的是这里的equal方法是用EPSILON属性实现的,不是JS自带的方法
19.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 console .log('Object.is(NaN, NaN)' ,Object .is(NaN , NaN ),'NaN === NaN' ,NaN === NaN );function A (name, age ) { this .name = name; this .age = age; } function B (name,sex ) { this .name = name; this .sex = sex; } let a = new A('A' ,18 );let b = new B('B' ,'女' );console .log('Object.assign(a,b)' ,Object .assign(a,b)); let C = { name : 'C' }; let D ={ age : 33 } Object .setPrototypeOf(C, D);console .log('Object.setPrototypeOf(C, D):' , C);console .log('Object.getPrototypeOf(C):' , Object .getPrototypeOf(C));
20.module模块化 把丑陋的代码实现包起来,只留出接口给外面看 (比如写一个冒泡排序,接口名字叫做快速排序,别人调用的时候就会觉得————好耶)
而且模块之间的内容是互不影响的,避免了污染
首先在同一目录下创建一个moduleTest.js文件,内容是
其中export修饰的内容会被暴露
1 2 3 4 5 6 7 export let date = '2021/07/05' ;export function myRecentLife ( ) { console .log('还在进行因为疫情被推迟的军训..' ); console .log('我想躺着写代码啊!!!' ); console .log('我想吃肉!!!' ); }
然后另一边,我们这样写
1 2 3 4 5 6 7 8 9 10 11 <script type="module" > import {date} from "./moduleTest.js" ; console .log(date); import * as m from './moduleTest.js' ; console .log(m); m.myRecentLife(); </script>
上图运行结果(一定要在服务器上运行啊!不然没有反应的 )注意事项 假如引入的两个模块中有重名内容, 比如 那么我们可以使用关键字as操作一手:
1 2 3 4 import {date} from "./moduleTest.js" ;import {date as date2} from "./moduleTest2.js" ;console .log("date:" ,date,"\ndate2:" ,date2);
(记得要在服务器上运行啊!!!)
后记 ES6大概就这样结束了,不过我还是想写下这多余的话
ES6更新了很多东西,这篇笔记是我一边学习一遍写代码做记录产生的,也是第一次接触到其中一些内容,所以难免有漏掉部分知识点,和理解分析不到位的情况,希望大家包涵谅解
后面如果有机会的话,我也会继续做ES相关的内容
祝大家能够不断进步