前几天,用es6的语法重写了个人一个代码库,说是重写,其实改动的并很少,工做量不大。在重写完了的时候,就我的总结了一下es6经常使用的一些经常使用的语法和比es5优越的方面。下面提到的语法可能也就是es6新特性的10%-20%,可是开发上占了80%左右的。下面的文章,按照es6经常使用新特性进行分类,文章说起的实例,有些是我代码库的小实例,有些是本身随便编的,你们知道就好!但愿能够帮到你们,若是你们以为文章有什么地方写错了,或者哪里写得不对,欢迎指出!javascript
1.可能还有些人不知道我说的的代码库是什么,简单的打下广告:这个代码库是我封装了一些javascript经常使用的小实例,好比: 数组去重, 字符替换, 经常使用Dom操做, 图片懒加载等的57个小实例( 查看说明)。代码也上传到github上面了!es5版本-- ec-do-1.1.4。es6版本-- ec-do-2.0.0。欢迎你们star。也但愿你们能够多给意见,或者和你们一块儿完善这个项目!
2.至于这个代码库的使用方法,去github看一下就知道了,这里很少说!
3.es6发布两年多了,如今都发布了es7,es8了,可是es7和es8更新的东西很少,能够参考下面两个连接! 聊聊ES7与ES8特性, 10分钟学会ES7+ES8。
let
和var
区别在于,let
有块级做用域的的区分概念。css
以下实例html
//至关于声明了一个全局的i变量。 for(var i=0;i<10;i++){ console.log(i) } console.log('最后的值:'+i)
//j只在这个for循环有效,若是在循环外调用就会报错 for(let j=0;j<10;j++){ console.log(j) } console.log('最后的值:'+j)
还有一个常见的使用场景是:好比一个页面有5个li
,索引固然就是0,1,2,3,4。点击某一个li,显示该li的索引。java
var oLi= document.querySelectorAll('li') for (var i = 0,len = oLi.length; i < len; i++){ oLi[i].onclick = function(){ console.log(i) } }
这样写,其实不管点击那个li
,都是显示5。由于当点击li
的时候,上面的代码已经执行完了,那么每一个i
,就是等于5,就显示5。git
用let就不会出现这个问题es6
var oLi= document.querySelectorAll('li') for (let i = 0,len = oLi.length; i < len; i++){ oLi[i].onclick = function(){ console.log(i) } }
用了let,若是点击第一个li
,就显示0,点击第三个li
,就显示2。这个你们能够自行尝试下!github
说完了let
,说下const
,const
初始化赋值以后就不能再改变赋值。以下图。segmentfault
这个我目前是用在引用插件,库,或者模块化开发上!数组
好比上面这个,在开发上能够因为重名而带来的异常!微信
箭头函数,使用的频率很是的高!写法也是很是的简洁和清晰!
以下的数组求和实例
//sumArr都是ecDo在这个对象里面的属性,可是你们看到es6和es5的定义方式不同,是es6简写方式。 //es6写法-隐式返回 sumArr(arr) { return arr.reduce((pre, cur) =>pre + cur) } //es6写法-显式返回 sumArr(arr) { return arr.reduce((pre, cur) =>{return pre + cur}) } //es5写法 sumArr: function (arr) { return arr.reduce(function (pre, cur) { return pre + cur }) },
还有一个经常使用的场景是,当使用了setTimeout
或者setInterval
的时候。以下‘图片懒加载的实例’(代码暂时能够不用看得太细,看图片就好,贴代码是为了让你们看到整个函数,不让你们蒙)。过程不详细说,看es6
和es5
的使用区别!
//es6写法,(若是看到函数参数有不懂的不用急,后面会提到!) loadImg(className = 'ec-load-img', num = 0, errorUrl = null) { let oImgLoad = document.getElementsByClassName(className); for (let i = 0, len = oImgLoad.length; i < len; i++) { //若是图片已经滚动到指定的高度 if (document.documentElement.clientHeight + document.documentElement.scrollTop > oImgLoad[i].offsetTop - num && !oImgLoad[i].isLoad) { //记录图片是否已经加载 oImgLoad[i].isLoad = true; //设置过渡,当图片下来的时候有一个图片透明度变化 oImgLoad[i].style.cssText = "transition: ''; opacity: 0;"; if (oImgLoad[i].dataset) { this.aftLoadImg(oImgLoad[i], oImgLoad[i].dataset.src, errorUrl, function (o) { //添加定时器,确保图片已经加载完了,再把图片指定的的class,清掉,避免重复编辑 setTimeout(()=>{ if (o.isLoad) { this.removeClass(o, className); o.style.cssText = ""; } }, 1000) }); } else { this.aftLoadImg(oImgLoad[i], oImgLoad[i].getAttribute("data-src"), errorUrl, function (o) { //添加定时器,确保图片已经加载完了,再把图片指定的的class,清掉,避免重复编辑 setTimeout(()=>{ if (o.isLoad) { this.removeClass(o, className); o.style.cssText = ""; } }, 1000) }); } (function (i) { setTimeout(()=>{ oImgLoad[i].style.cssText = "transition:all 1s; opacity: 1;"; }, 16) })(i); } } } //es5写法 loadImg: function (className, num, errorUrl) { var _className = className || 'ec-load-img', _num = num || 0, _this = this,_errorUrl=errorUrl||null; var oImgLoad = document.getElementsByClassName(_className); for (var i = 0, len = oImgLoad.length; i < len; i++) { //若是图片已经滚动到指定的高度 if (document.documentElement.clientHeight + document.documentElement.scrollTop > oImgLoad[i].offsetTop - _num && !oImgLoad[i].isLoad) { //记录图片是否已经加载 oImgLoad[i].isLoad = true; //设置过渡,当图片下来的时候有一个图片透明度变化 oImgLoad[i].style.cssText = "transition: ''; opacity: 0;" if (oImgLoad[i].dataset) { this.aftLoadImg(oImgLoad[i], oImgLoad[i].dataset.src, _errorUrl, function (o) { //添加定时器,确保图片已经加载完了,再把图片指定的的class,清掉,避免重复编辑 setTimeout(function () { if (o.isLoad) { _this.removeClass(o, _className); o.style.cssText = ""; } }, 1000) }); } else { this.aftLoadImg(oImgLoad[i], oImgLoad[i].getAttribute("data-src"), _errorUrl, function (o) { //添加定时器,确保图片已经加载完了,再把图片指定的的class,清掉,避免重复编辑 setTimeout(function () { if (o.isLoad) { _this.removeClass(o, _className); o.style.cssText = ""; } }, 1000) }); } (function (i) { setTimeout(function () { oImgLoad[i].style.cssText = "transition:all 1s; opacity: 1;"; }, 16) })(i); } } }
代码贴了这么多,其实区别就三小块
简单解释一下:当使用箭头函数了,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。(好比上面提到的实例,setTimeout
里面的this,本来指向window,可是使用的箭头函数,就指向ecDo这个对象)
缘由是箭头函数没有this,它的this是继承外面的,所以内部的this就是外层代码块的this。
模板字符串,这个日常使用的频率也很是高,并且也很实用!
以下实例:到某一个时间的倒计时
//es6写法 getEndTime(endTime) { let startDate = new Date(); //开始时间,当前时间 let endDate = new Date(endTime); //结束时间,需传入时间参数 let t = endDate.getTime() - startDate.getTime(); //时间差的毫秒数 let d = 0, h = 0, m = 0, s = 0; if (t >= 0) { d = Math.floor(t / 1000 / 3600 / 24); h = Math.floor(t / 1000 / 60 / 60 % 24); m = Math.floor(t / 1000 / 60 % 60); s = Math.floor(t / 1000 % 60); } return `剩余时间${d}天${h}小时${m}分钟${s}秒"`; } //es5写法 getEndTime: function (endTime) { var startDate = new Date(); //开始时间,当前时间 var endDate = new Date(endTime); //结束时间,需传入时间参数 var t = endDate.getTime() - startDate.getTime(); //时间差的毫秒数 var d = 0, h = 0, m = 0, s = 0; if (t >= 0) { d = Math.floor(t / 1000 / 3600 / 24); h = Math.floor(t / 1000 / 60 / 60 % 24); m = Math.floor(t / 1000 / 60 % 60); s = Math.floor(t / 1000 % 60); } return "剩余时间" + d + "天 " + h + "小时 " + m + " 分钟" + s + " 秒"; }
可能你们还不以为模板字符串怎么好用,那么接下来再说一个实例,好比往一个div
添加一大段的html
内容时。es5的作法是
var obj={ author:'守候', time:'2017.11.8', thing:'看下模板字符串的方便性。' } $("#test").append( "<p>这是<i>" + obj.author+ "</i> " + "写的一个实例。这个实例是为了" + "<i>" + obj.thing + "</i>"+"<span>写做日期是:"+obj.time+ "</span></p>" );
而使用es6,就简单多了
let obj={ author:'守候', time:'2017.11.8', thing:'看下模板字符串的方便性。' } $("#test").append( `<p> 这是<i>${obj.author}</i> 写的一个实例。这个实例是为了 <i> ${obj.thing}</i> <span>写做日期是:${obj.time}</span> </p>` );
解构赋值这个用得算是比较多的,简单明了,就是一个简写方式!
//es5 var name='守候' var sex='男' var info= {name:name, sex: sex} console.log(info) //Object {name: "守候", sex: "男"} //es6 let name='守候' let sex='男' let info= {name, sex} console.log(info) //Object {name: "守候", sex: "男"} //es6也能够反过来 let info={name: "守候", sex: "男"}; let {name,sex}=info; console.log(name,sex)// "守候" "男"
default,就是函数参数的默认值,很好理解
比格式化处理字符串这个函数
//es6写法 formatText(str, size = 3, delimiter = ',') { let regText = '\\B(?=(\\w{' + size + '})+(?!\\w))'; let reg = new RegExp(regText, 'g'); return str.replace(reg, delimiter); } //es5写法 formatText: function (str, size, delimiter) { var _size = size || 3, _delimiter = delimiter || ','; var regText = '\\B(?=(\\w{' + _size + '})+(?!\\w))'; var reg = new RegExp(regText, 'g'); return str.replace(reg, _delimiter); }
rest这个我不知道怎么说,看下面的实例吧
function param(first,...all){ console.log(first) console.log(all) console.log(Object.prototype.toString.call(all)) } animals('第一个', '第二个', '第三个')
这样写,all就是一个数组,不用像arguments
那样转成数组!
这两个对应的就是对应的特性就是,模块化开发,这个能够说是最实用的一个新特性了!功能也强大,可是写起来就很简单!就几个代码!看图吧!
封装模块的时候,用export把模块暴露出去
须要使用的时候,用import引进行来,完事
顺便提一下,另外一个按需引入的方法
repeat方法返回一个新字符串,表示将原字符串重复n次。
'守候'.repeat(3) //"守候守候守候"
includes
:是否找到了参数字符串,返回布尔值。startsWith
:参数字符串是否在原字符串的头部,返回布尔值。endsWith
:参数字符串是否在原字符串的尾部,返回布尔值。
三个方法都接受两个参数,第一个参数是参数字符串,第二个是开始检索的位置
var str='我就是守候' str.startsWith('我就是')//true str.startsWith('我')//true str.startsWith('我',2)//false str.startsWith('守候')//false str.endsWith('守候')//true str.includes('守候')//true str.includes('我',3)//false
padStart
:若是字符串不够指定长度,在头部补全指定字符padEnd
:若是字符串不够指定长度,在尾部补全指定字符
两个方法都接收两个参数,第一个是指定字符串的最小长度,第二个用来补全的字符串。若是指定字符串的长度,等于或大于指定的最小长度(第一个参数)。就直接返回原字符串,若是忽略第二个参数,就使用空格补全原字符串!
var str='守候' str.padEnd(10,'123')//"守候12312312" str.padStart(10,'123')//"12312312守候" str.padEnd(10)//"守候 " str.padStart(10)//" 守候" str.padStart(1)//"守候" str.padEnd(1)//"守候"
检查一个值是否为NaN
Number.isNaN(NaN)//true Number.isNaN(15)//false
判断一个值是否为整数,须要注意的是,好比1和1.0都是整数。
Number.isInteger(1)//true Number.isInteger(1.0)//true Number.isInteger(1.1)//false
判断一个数究竟是正数、负数、仍是零
Math.sign(-10)// -1 Math.sign(10)// +1 Math.sign(0)// +0 Math.sign(-0)// -0 Math.sign(NaN)// NaN Math.sign('10')// +1 Math.sign('守候')// NaN Math.sign('')// 0 Math.sign(true)// +1 Math.sign(false)// 0 Math.sign(null)// 0
去除一个数的小数部分,返回整数部分
Math.trunc(1.1)//1 Math.trunc(-1.1)//-1 Math.trunc(-0.1)//-0 Math.trunc('123.456')//123 Math.trunc('守候')//NaN
用于对象的合并,复制到目标对象。
var _name={name:'守候'},sex={sex:'男'},city={'city':'广州'} Object.assign(_name,sex,city)//{name: "守候", sex: "男", city: "广州"} var info1={name:'守',sex:'男'},info2={name:'候',city:'广州'} Object.assign(info1,info2)//{name: "候", sex: "男", city: "广州"}
克隆原来这样对象,这样克隆对象,修改了info1或者info3,不会影响info3或者info1,可是Object.assign并非深拷贝。详细的能够参考我以前的文章--对象深浅拷贝
var info1={name:'守',sex:'男'} var info3=Object.assign(info1,{})//{name:'守',sex:'男'}
根据对象自身可遍历的键名进行遍历,返回一个数组
var info={name: "守候", sex: "男", city: "广州"} Object.keys(info)//["name", "sex", "city"]
根据对象自身可遍历的键值进行遍历,返回一个数组
Object.values(info)//["守候", "男", "广州"]
根据对象自身可遍历的键值对进行遍历,返回一个数组
Object.entries(info)//[["name", "守候"],["sex", "男"],["city", "广州"]]
from
用于将两类对象转为真正的数组:相似数组的对象和可遍历的对象
Array.from('守候')//["守", "候"] //常见的使用方式还有-将Dom集合和arguments转成真正的数组 let oLi = document.querySelectorAll('li'); Array.from(oLi ).forEach(function (item) { console.log(item); }); // arguments对象 function fn() { let args = Array.from(arguments); } //顺便说下Set let newSet = new Set(['a', 'b','a','c']) Array.from(newSet) // ['a', 'b','c'] //ES6 新增的数据结构--Set。它相似于数组,可是成员的值都是惟一的,不重复的。 //相信你们很容易想到怎么用了,好比数组去重,用Set实现就简单多了。 removeRepeatArray(arr) { //return [Array.from(arr)] return [...new Set(arr)] }
find
方法,用于找出第一个符合条件的数组成员。若是没找到符合条件的成员就返回underfind
//第一个大于2的成员 [1, 2, 3, 4].find((n) => n > 2)//3
findIndex
方法,用于找出第一个符合条件的数组成员的索引。
//第一个大于2的成员的索引 [1, 2, 3, 4].findIndex((n) => n > 2)//2
includes
方法,用于某个数组是否包含给定的值,返回一个布尔值。若是没找到符合条件的成员就返回underfind
[1, 2, 3].includes(2)//true [1, 2, 3].includes(5)//false [1, 2, NaN].includes(NaN)//true
好了,关于es6的经常使用语法和比es5优越的方面区别,就说到这里了,这些是我在日常开发用的比较多。若是想详细学习es6,移步到阮一峰的-ECMAScript 6 入门。这些语法相信在开发了已经占了很大的一个比重了!固然若是你们还有什么好的语法,API推荐,或者以为我哪里写错了,写得很差,欢迎给出宝贵的意见,指点下迷津。也期待你们相互学习,一块儿进步!
-------------------------华丽的分割线--------------------
想了解更多,关注关注个人微信公众号:守候书阁