1.前言
前幾天,用es6的語法重寫了我的一個程式碼庫,說是重寫,其實改動的並不多,工作量不大。在重寫完了的時候,就個人總結了一下es6常用的一些常用的語法和比es5優越的方面。下面提到的語法可能也就是es6新特性的10%-20%,但是開發上佔了80%左右的。下面的文章,按照es6常用新特性進行分類,文章提及的例項,有些是我程式碼庫的小例項,有些是自己隨便編的,大家知道就好!希望可以幫到大家,如果大家覺得文章有什麼地方寫錯了,或者哪裡寫得不對,歡迎指出!
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。
2.let const
let
和var
區別在於,let
有塊級作用域的的區分概念。
如下例項
//相當於宣告瞭一個全域性的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的索引。
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。
用let就不會出現這個問題
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。這個大家可以自行嘗試下!
說完了let
,說下const
,const
初始化賦值之後就不能再改變賦值。如下圖。
這個我目前是用在引用外掛,庫,或者模組化開發上!
比如上面這個,在開發上可以由於重名而帶來的異常!
3.arrow function
箭頭函式,使用的頻率非常的高!寫法也是非常的簡潔和清晰!
如下的陣列求和例項
//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。
4.template string
模板字串,這個平常使用的頻率也非常高,而且也很實用!
如下例項:到某一個時間的倒數計時
//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>`
); 複製程式碼
5.destructuring
解構賦值這個用得算是比較多的,簡單明瞭,就是一個簡寫方式!
//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)// "守候" "男"
複製程式碼
6.default, rest
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
那樣轉成陣列!
7.export & import
這兩個對應的就是對應的特性就是,模組化開發,這個可以說是最實用的一個新特性了!功能也強大,但是寫起來就很簡單!就幾個程式碼!看圖吧!
封裝模組的時候,用export把模組暴露出去
需要使用的時候,用import引進行來,完事
順便提一下,另一個按需引入的方法
8.API推薦
8-1.字串
repeat
repeat方法返回一個新字串,表示將原字串重複n次。
'守候'.repeat(3)
//"守候守候守候"複製程式碼
includes & startsWith & endsWith
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
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)//"守候"複製程式碼
8-2.數值
isNaN
檢查一個值是否為NaN
Number.isNaN(NaN)//true
Number.isNaN(15)//false複製程式碼
isInteger
判斷一個值是否為整數,需要注意的是,比如1和1.0都是整數。
Number.isInteger(1)//true
Number.isInteger(1.0)//true
Number.isInteger(1.1)//false
複製程式碼
sign
判斷一個數到底是正數、負數、還是零
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
複製程式碼
trunc
去除一個數的小數部分,返回整數部分
Math.trunc(1.1)//1
Math.trunc(-1.1)//-1
Math.trunc(-0.1)//-0
Math.trunc('123.456')//123
Math.trunc('守候')//NaN
複製程式碼
8-3.物件
assign
用於物件的合併,複製到目標物件。
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:'男'}複製程式碼
keys
根據物件自身可遍歷的鍵名進行遍歷,返回一個陣列
var info={name: "守候", sex: "男", city: "廣州"}
Object.keys(info)//["name", "sex", "city"]
複製程式碼
values
根據物件自身可遍歷的鍵值進行遍歷,返回一個陣列
Object.values(info)//["守候", "男", "廣州"]
複製程式碼
entries
根據物件自身可遍歷的鍵值對進行遍歷,返回一個陣列
Object.entries(info)//[["name", "守候"],["sex", "男"],["city", "廣州"]]
複製程式碼
8-4.陣列
from
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
find
方法,用於找出第一個符合條件的陣列成員。如果沒找到符合條件的成員就返回underfind
//第一個大於2的成員
[1, 2, 3, 4].find((n) => n > 2)//3複製程式碼
findIndex
findIndex
方法,用於找出第一個符合條件的陣列成員的索引。
//第一個大於2的成員的索引
[1, 2, 3, 4].findIndex((n) => n > 2)//2複製程式碼
includes
includes
方法,用於某個陣列是否包含給定的值,返回一個布林值。如果沒找到符合條件的成員就返回underfind
[1, 2, 3].includes(2)//true
[1, 2, 3].includes(5)//false
[1, 2, NaN].includes(NaN)//true複製程式碼
9.小結
好了,關於es6的常用語法和比es5優越的方面區別,就說到這裡了,這些是我在平常開發用的比較多。如果想詳細學習es6,移步到阮一峰的-ECMAScript 6 入門。這些語法相信在開發了已經佔了很大的一個比重了!當然如果大家還有什麼好的語法,API推薦,或者覺得我哪裡寫錯了,寫得不好,歡迎給出寶貴的意見,指點下迷津。也期待大家相互學習,一起進步!
-------------------------華麗的分割線--------------------
想了解更多,關注關注我的微信公眾號:守候書閣