橫向對比ES5哲泊、ES6剩蟀、ES7、ES8

前言

常用JS的代碼片段

//連接數組
let arrA =[10,20,30]
let arrB = [40,50,60]
let arrC = [...arrA,...arrB]

//數組去掉重復項
let arrD = [30,30,40,40,50,50]
let arrE =[...new Set(arrD)]

//查找索引

[10,20,30].indexOf(20)

//遍歷數組

[10,20,30].forEach((value,index)=>{

console.log(`${value} ${index}`)

})

//映射新數組

let arrF = [10,20,30].map(v=>v*2)

//檢驗數組中每個元素

[10,20,30].every(v=>v>10)

//是否有元素通過測試

[10,20,30].some(v=>v>10)

//過濾數組

[10,20,30].filter(v=>v>10)

//獲取對象的key切威、value育特、es6遍歷數組

Object.keys({a:1,b:2},{a:3,b:11})
Object.values({a:1,b:2},{a:3,b:11})
Object.entries({a:1,b:2},{a:3,b:11})

//獲取對象里元素數量

Object.keys({a:1,b:2},{a:3,b:11}).length



前言

ECMAScript是ECMA組織制定的腳本語言規(guī)范,該規(guī)范來源于網景的Javascript和微軟的Jscript先朦,ECMAScript-262明確的定義了JavaScript缰冤。最初,JavaScript由Brendan Eich發(fā)明喳魏,最先出現在Navigator 2.0瀏覽器中锋谐。ES大會定期整理并發(fā)布新的JS版本。

ES版本 發(fā)布時間 新增特性
ES5 200911 擴展了Object截酷、Array涮拗、Function等的功能
ES6(2015) 201506 類、模塊化迂苛、剪頭函數三热、函數參數默認值、模版字符串三幻、解構賦值就漾、延展操作符、對象屬性簡寫(對象擴展念搬,還有計算屬性)抑堡、Promise、let朗徊、const(塊級作用域)首妖、新數據結構Set、Map爷恳、Symbol
ES7(2016) 201603 Array.prototype.includes()有缆、指數操作符
ES8(2017) 201706 async/await、Object.values()、Object.entries()棚壁、String padding杯矩、函數參數列表結尾允許逗號、Object.getOwnPropertyDescriptors()等

延展操作符嚴格來說袖外,不算ES6標準史隆,但是babel支持,就寫在這里了

ES5我就不說了曼验,主要說說其他幾個都更新了什么逆害,另外可以使用babel將其他語法轉換為es5,此外babel還支持裝飾器蚣驼、async-await因此,就是瀏覽器有些不支持es6等更高級的語法相艇,也還是可以基于babel來使用更高級的語法

部分ES6 新增特性說明

新數據結構

Set(不可重復元素集合)颖杏、Map、Symbol

JS語言原來實現面向對象是直接通過原型的方式進行坛芽,這就讓Java留储、Object-c、C#等面向對象語言的程序員比較難以理解了咙轩。隨著JS能做的事情增多获讳,因此,才會原生的引入class這個概念活喊。我們來看看下邊這段代碼丐膝,來看看類與繼承的代碼如何寫,此次需要注意的是钾菊,繼承的時候帅矗,super要寫在子類構造函數的最頂部。另外煞烫,從源碼層面可以看出浑此,class、extends滞详、constructor都是prototype的語法糖

class Animal {
    constructor(name, feature) {
        this.name = name
        this.feature = feature
    }

    toString() {
        console.log('name:' + this.name + ',feature:' + this.feature)
        // return 'Animal done'
    }
}

var animal = new Animal('monky', 'beauty')//實例化
animal.toString()

console.log(animal.hasOwnProperty('name'))//true
console.log(animal.hasOwnProperty('toString'))//false
console.log(animal.__proto__.hasOwnProperty('toString'))//true

//繼承

class Cat extends Animal {
    constructor(action) {
        super('cat', 'sex')
        this.action = action
    }

    toString(){
        // console.log(super.toString())
        super.toString()
    }
}

var cat = new Cat('catch')
cat.toString()

console.log(cat instanceof Cat)//true
console.log(cat instanceof Animal)//true

模塊化(Module)

ES6實現了模塊化凛俱,于是告別了基于commonjs的標準,使用require.js的AMD模式和sea.js的CMD模式來實現模塊化的古老方式料饥。

模塊化主要基于export(導出蒲犬,還有export default)和import(引用,還有import * as)兩個關鍵字來實現岸啡,這就為JS引入了一個相對容易理解的封裝的概念(以前是基于函數作用域和閉包暖哨,通過底層直接實現,現在可以優(yōu)雅的通過關鍵字原生實現)

export定義了對外開放的接口,import定義了引用哪些接口篇裁。模塊化為js創(chuàng)建了比較容易理解的命名空間沛慢,防止函數的命名沖突。

export

export var name = 'Ryan'//導出變量
export const sort = Math.sqrt//導出常量
export {name, sort}//導出對象(模塊)
export function aModule(){return 1000}//導出函數

import

import defaultMethod,{otherMethod} from 'aModule'//xxx.js

箭頭(Arrow)函數

1.=>是function的縮寫
2.箭頭函數與包圍它的代碼共享同一個this达布。這種情況下团甲,就很好的解決了this的指向問題。我在寫一個錢包服務器的時候黍聂,做過這樣一個事情躺苦,通過定義var self = this,或者var that = this來引用外圍的this产还,也就是我想用其他function中的this匹厘,我就需要想將其復制到一個全局的或者是類的屬性上。借助=>脐区,就不需要這種模式了愈诚。箭頭函數的書寫形式如下

()=>100
v=>x+1
(a,b)=>a-b
()=>{var=u}//return undefined
p=>{return 100}

箭頭函數與bind的注意事項

箭頭函數和bind方法,每次被執(zhí)行后都會返回一個新的函數引用牛隅,因此炕柔,如果還需要對函數的引用做些事情的話(例如卸載監(jiān)聽器),那么你還需要保存之前的引用媒佣。以bind為例匕累,我們說明一下:

class PauseMenu extends React.Component {
    componentWillMount() {
        AppStateIOS.addEventListener('change', this.onAppPaused.bind(this))
    }
    componentWillUnmount() {
        AppStateIOS.removeEventListener('change', this.onAppPaused.bind(this))
    }
    onAppPaused(event) { }
}

此處,因為bind每次都會調用一個新的函數引用默伍,因此欢嘿,造成卸載的不是原來的監(jiān)聽,造成卸載失敗也糊。此處應該修改為

class PauseMenu extends React.Component {
    constructor(props) {
        super(porps)
        this._onAppPaused = this.onAppPaused.bind(this)
    }
    componentWillMount() {
        AppStateIOS.addEventListener('change', this._onAppPaused)
    }
    componentWillUnmount() {
        AppStateIOS.removeEventListener('change', this._onAppPaused)
    }
    onAppPaused(event) { }
}

那么基于剪頭函數际插,我們還可以使用箭頭函數來做,因為箭頭函數會共享包圍它的this显设,因此框弛,這樣就可以簡單明了的處理返回新的函數引用的問題了。

class PauseMenu extends React.Component {
    componentWillMount() {
        AppStateIOS.addEventListener('change', this.onAppPaused)
    }
    componentWillUnmount() {
        AppStateIOS.removeEventListener('change', this.onAppPaused)
    }
    onAppPaused = event => { }
}

函數參數默認值

function foo(height = 50,color = '#fff")

如果不使用函數默認值捕捂,就會有個小問題瑟枫。

function foo (height,color)
{
var height = height||50
var color = color||'red'
}

如果參數的布爾值是false,例如指攒,foo(0慷妙,''),因為0的布爾值是false允悦,這樣height的取值將會是50膝擂,color也會取red,因此,函數的默認值不僅能使代碼簡潔架馋,也幫助規(guī)避一些風險

模版字符串

let name = 'name'+first+''+last+''

使用模版字符串狞山,就簡潔了很多。從此告別 +號拼接字符串的尷尬叉寂,并且還支持多行字符串

let name = `name is ${first} ${last}`

let names = `
xiaohong

zhangzhang

dada

`


解構賦值

解構賦值可以方便快速的從數組或者對象中提取賦值給定義的變量萍启。

獲取數組中的值

從數組中獲取值并賦值到變量中,變量的順序與數組中對象順序對應屏鳍。

var foo = [1,2,3,4,5]

var [one,twe,three] = foo
console.log(one)//1
console.log(twe)//2
console.log(three)//3

如果想要會略某些值勘纯,則可以

var [first,,last] = foo
console.log(first)//1
console.log(last)//5

也可以先聲明變量

var a,b

[a,b] = [1,2]

console.log(a)//1
console.log(b)//2

如果沒有從數組中獲取到值,可以為變量設置一個默認值

var a,b

[a=5,b=7]=[1]

console.log(a)//1
console.log(b)//7

方便的交互兩個變量的值

var a=1
var b = 3

[a,b]=[b,a]

console.log(a)//3
console.log(b)//1

獲取對象中的值

const student={
name:'xxx',
age:'19',
city:'bj'
}

const {name, age,city}=student

console.log(name)//xxx
console.log(age)//19
console.log(city)//bj

延展操作符(Spread operator)

延展操作符 = ...可以在函數調用/數組構造時钓瞭,將數組表達式或者string在語法層面展開驳遵,還可以在構造對象時,將對象表達式按key-value的方式展開山涡。

函數調用

function(...iterableObj)

數組構造或者字符串

[...iterableObj,'4',...'hello',6]

es2018下構造對象時堤结,進行克隆或者屬性拷貝

let objClone={...obj}

應用場景

function sum(x,y,x){

return x+y+z

}

const numbers = [1,2,3]

不使用延展操作符

sum.apply(null, numbers)

使用延展操作符

sum(...numbers)

或者在構造數組時

如果沒有展開語法,只能組合使用push佳鳖,splice,concat,slice
將已有數組元素變?yōu)樾聰到M的一部分

const people=['jan','tom']
const person = ['ali',...people,'alliance','ketty']
console.log(person)//Ali,jan,tom,alliance,ketty

另外媒惕,還有一個例子

var arr =[1,2,3]
var arr2=[...arr]
arr2.push(4)
console.log(arr2)//1,2,3,4

展開語法與Obj.assign()行為一致系吩,都是執(zhí)行淺拷貝,也就是只遍歷一層妒蔚,不會遍歷父對象相關的數據

var arr1=[0,1,2]
var arr2=[3,4,5]
var arr3=[...arr1,...arr2] 等同于var arr4 = arr1.concat(arr2)

es2018中增加了對對象的支持

var obj1 = {foo:1,foo2:2}
var obj2={foo3:12,foo4:30}

var clonedObj={...obj1}
var mergedObj={...obj1,...obj2}

...在react中的應用

我們封裝組件的時候穿挨,會對外公開props用于參數傳遞。我們一般都會使用...props進行參數的傳遞與遍歷數據

<CustomComponent name='Jine' age={21} />
等價于
const params = {
name:'jine',
age:21
}

<CustomComponent {...params} />

我們還可以配合結構賦值肴盏,避免傳入一些不必要的參數

var param = {
name:123,
title:456,
type:789
}

var {type,...other} = param

<CustomComponent type='normal' number={2} {...other} />
等價于

<CustomComponent type='normal' number={2} name=123,title=456/>

對象屬性簡寫

設置一個對象時科盛,不指定屬性名

es5
const name=ming,age=18,city=Shanghai
const student={
name:name,
age:age,
city:city
}
es6
const name=ming,age=18,city=Shanghai
const student={
name,
age,
city
}


Promise

Promise是異步編程的一種解決方案,對callback做進一步的封裝和優(yōu)化菜皂。Promise由社區(qū)提出和實現贞绵,es6將其寫進了語言標準,并統(tǒng)一了用法恍飘,提供了原生的promise支持榨崩。此處詳細解答,請看我的另外一篇blog

let章母、const

let母蛛、const提供塊級作用域,之前只能通過函數+閉包的方式來模擬塊級作用域乳怎。那么let與const的區(qū)別呢彩郊?let聲明可變變量,類型和值都可以改變醉者。const聲明不變變量(可以認為是常量瘫拣,聲明后就不能再次賦值了)暑脆,聲明變量后箍铭,必須馬上初始化颅崩,不能留到以后賦值赵誓。

es5
{var a=19}

console.log(a)//19
es6

{
let a=20
}
console.log(a)//a is not defined


部分ES7新增特性說明

Array.prototype.includes()

用來判斷一個數組是否包含指定的值菲宴,包含返回true艰管,不包含返回false

arr.includes(x)等價于arr.indexOf(x)>0

指數操作符(**)

** 與Math.pow(..)等效的計算結果

Math.pow(2,10)等價于2**10

部分ES8新增特性說明

async/await

異步轉同步前方,可以看我的另外一片blog狈醉。我們主要是用async/await來順序獲取異步函數返回值。
另外惠险,依托于Promise.all還可以實現await的并發(fā)調用苗傅,這樣就避免了同步調用的時間等待,提高了程序的整體效率班巩。

async function charCountAdd(data1, data2) {

    const [d1, d2] = await Promise.all([charCount(data1), charCount(data2)])
    // const d1 = await charCount(data1)
    // const d2 = await charCount(data2)
    return d1 + d2

}

charCountAdd('Hello','Hi').then(console.log)
function charCount(data){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve(data.length)
        },5000)
    })
}
//捕捉錯誤渣慕,可以使用try catch,也可以在then后追加catch

Object.values()

Object.values()類似于Object.keys()抱慌,返回Object自身的所有屬性值逊桦,不包括繼承的值。

const obj={a:12,b:13,c:14}
es7
const vals=Object.keys(obj).map(key=>obj[key])
console.log(vals)//12,13,14
es8
const vals =Object.values(obj)
console.log(vals)//12,13,14

Object.entries

Object.entries()函數返回一個給定對象自身可枚舉屬性的鍵值對的數組

const obj={a:12,b:13,c:14}
es7
Object.keys(obj).forEach(key=>{
console.log('key:'+key+'values:'+obj[key])//12,13,14
})
es8
for (let [key,value] of Object.entries(obj)){
console.log('key: ${key} values: ${value}')//12,13,14
}

String padding

es8中抑进,新增String.prototype.padStart(targetLength,[padString])和String.prototype.padEnd允許將空字符串或者其他字符串添加到原始字符串的開頭或者結尾

console.log('0.0'.padStart(4,'10'))//10.0
console.log('0.0'.padStart(20))//                    0.0
console.log('0.0'.padEnd(4,'0'))//0.00
console.log('0.0'.padEnd(10,'0'))//0.000000000

編碼規(guī)范

單引號强经、雙引號

node中,單引號雙引號有很多的時候是可以混用的寺渗,因此匿情,此處也是一個重點,如果不注意信殊,很容易出現奇怪的錯誤炬称。在JSON中,全部請使用雙引號涡拘,在其他地方也請使用雙引號玲躯,如果在雙引號中又存在引號,請使用單引號做區(qū)分鳄乏。

分號

必須記得加分號府蔗,不加分號就跟耍流氓一樣。

縮進汞窗、空格姓赤、大括號、小括號仲吏、逗號不铆、數組蝌焚、對象等的基本格式

通過IDE協助縮進,具體方式請根據不同的IDE進行總結誓斥,本處簡單介紹webstrom的使用方式----全選之后只洒,剪切代碼,然后重新粘貼到代碼編輯文本輸入框中劳坑。

變量聲明

如果是ES5的話永遠都要加var毕谴,如果是ES6.....如果是ES7....

命名

變量命名:名詞+小駝峰
方法命名:動詞開頭+名詞+小駝峰
類命名(ES6開始有類嘍,MD以前都是原型....艸):大駝峰
常量命名:大寫字母 + 下劃線
文件命名:小寫字母 + 下劃線
中間件(包)命名:小寫字母

==和===

==用于直接比較數值的情況
===用于其他情況

字面量

這個字面量的相關說明來源于樸靈的深入淺出距芬,我在這里做一下搬運工涝开。書中說“請盡量使用{}、[]替代new Object()框仔、new Array()舀武,不要使用string(new String)、bool(new Boolean)离斩、number(new Number)對象類型”银舱,當然,此處應該更多的是針對ES5下的相關語法跛梗,如果是ES6寻馏、ES7應該完全不一樣了。(需要補充ES6核偿、ES7的相關語法和規(guī)范)

作用域

依然會存在ES5诚欠、ES6、ES7不一致的地方宪祥。
ES5中沒有塊級語句聂薪,最多是通過with來增加一個臨時的塊級變量復用區(qū)域家乘,但是with又不是特別安全的蝗羊。
ES6有了塊級區(qū)域,變量范圍跟java差不多了

數組

數組不要用for in進行循環(huán)仁锯,詳見代碼:

var foo = [];
foo[100] = 100;
//循環(huán)1
for (var i in foo) {
console.log(i);
}
//循環(huán)2
for (var i = 0; i < foo.length; i++) {
console.log(i);
}

循環(huán)1只會執(zhí)行一次耀找,循環(huán)2則會執(zhí)行0~100,因此數組就不要for in 了 业崖,因為野芒,我們可能希望遍歷數組中的全部數據,而不是非undefine的數據双炕。

異步

異步回調第一個參數應該是錯誤指示狞悲。

類與模塊

依然會存在ES5、ES6妇斤、ES7不一致的地方摇锋。(之后做整理)
類繼承丹拯、導出都不一樣。

在es5下荸恕,類繼承推薦的方式是

function Socket(options){
//....
stream.Stream.call(this);
//....
}

util.inherits(Socket,stream.Stream);

最佳實踐的理論

1.注釋要寫成/** */的形式乖酬,方面工具導出
2.遵循原來項目的編碼規(guī)范
3.基于JSLint或者JSHint進行代碼質量管理,可以在編輯器中提醒不規(guī)范的信息融求,我們可以增加.jshintrc文件咬像。這個可以去github上去查找并學習。
4.代碼提交的hook腳本生宛,例如precommit县昂,這個需要學習整理。
5.持續(xù)集成茅糜,一方面七芭,持續(xù)集成代表著代碼質量的掃描,可以定時掃描或者觸發(fā)式掃描蔑赘,另一方面狸驳,可以通過集中的平臺統(tǒng)計代碼質量的好壞趨勢,根據統(tǒng)計結果可以判定團隊中的個人對編碼規(guī)范的執(zhí)行情況缩赛,決定用寬松的質量管理還是嚴格的質量管理耙箍。
6.可以使用CoffeeScript規(guī)范(編譯式的js,還有typescript等)酥馍,來避免一些不必要的編碼規(guī)范的問題

說明 規(guī)則或方法
空格 利用IDE的排版功能自動增加需要的空格辩昆。(+、-旨袒、*汁针、/、%砚尽、(施无、)等操作符前后都增加空格)
縮進 利用IDE的排版功能自動增加需要的縮進。與Java編碼規(guī)范相同
變量聲明 使用var聲明變量
單引號必孤、雙引號 json中必須使用雙引號猾骡,es5 use strict下也必須使用雙引號,其他地方單引號雙引號可以隨便用
分號 必須增加分號在語句的結尾
變量命名 小駝峰
方法命名 小駝峰敷搪,動詞開頭
類命名 大駝峰
常量命名 都是大寫字母兴想,使用下劃線隔開每個單詞
文件命名 都是小寫字母,使用下劃線隔開每個單詞
對外文件命名 都是小寫字母赡勘,使用下劃線開頭嫂便,并使用下劃線隔開每個單詞
包名 都是小寫字母,仿照npm庫進行包的命名
比較操作 盡量使用===闸与,數值比較可以用==
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末毙替,一起剝皮案震驚了整個濱河市曼振,隨后出現的幾起案子,更是在濱河造成了極大的恐慌蔚龙,老刑警劉巖冰评,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異木羹,居然都是意外死亡甲雅,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門坑填,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抛人,“玉大人,你說我怎么就攤上這事脐瑰⊙叮” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵苍在,是天一觀的道長绝页。 經常有香客問我,道長寂恬,這世上最難降的妖魔是什么续誉? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮初肉,結果婚禮上酷鸦,老公的妹妹穿的比我還像新娘。我一直安慰自己牙咏,他們只是感情好臼隔,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妄壶,像睡著了一般摔握。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盯拱,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天盒发,我揣著相機與錄音例嘱,去河邊找鬼狡逢。 笑死,一個胖子當著我的面吹牛拼卵,可吹牛的內容都是我干的奢浑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼腋腮,長吁一口氣:“原來是場噩夢啊……” “哼雀彼!你這毒婦竟也來了壤蚜?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤徊哑,失蹤者是張志新(化名)和其女友劉穎袜刷,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體莺丑,經...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡著蟹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了梢莽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萧豆。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖昏名,靈堂內的尸體忽然破棺而出涮雷,到底是詐尸還是另有隱情,我是刑警寧澤轻局,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布洪鸭,位于F島的核電站,受9級特大地震影響仑扑,放射性物質發(fā)生泄漏卿嘲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一夫壁、第九天 我趴在偏房一處隱蔽的房頂上張望拾枣。 院中可真熱鬧,春花似錦盒让、人聲如沸梅肤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姨蝴。三九已至,卻和暖如春肺缕,著一層夾襖步出監(jiān)牢的瞬間左医,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工同木, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留浮梢,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓彤路,卻偏偏與公主長得像秕硝,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子洲尊,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內容

  • 前面的話 函數是所有編程語言的重要組成部分远豺,在ES6出現前奈偏,JS的函數語法一直沒有太大的變化,從而遺留了很多問題躯护,...
    CodeMT閱讀 817評論 0 1
  • 1惊来、let和const命令 let聲明的變量只在let所在的代碼塊有效,即有塊級作用域棺滞,不同于var唁盏; let定義...
    風之化身呀閱讀 379評論 0 1
  • 一、ES6簡介 ? 歷時將近6年的時間來制定的新 ECMAScript 標準 ECMAScript 6(亦稱 ...
    一歲一枯榮_閱讀 6,062評論 8 25
  • [TOC] 參考阮一峰的ECMAScript 6 入門參考深入淺出ES6 let和const let和const都...
    郭子web閱讀 1,773評論 0 1
  • 又是好久沒寫文章检眯,又給自己找了一大堆理由厘擂。從今天起,以后按部就班每天寫一寫锰瘸,不斷提高刽严,不斷進步。
    貓哥閱讀 514評論 0 1