//對象字面量
/*
以{}形式直接表示的對象
*/
var book = {
title:"Modular ES6",
author:"Nicolas",
publisher:"O`Reilly"
}
/*
屬性的簡潔表示法
*/
//ago
var listeners = []
function listen(){
}
var events = {
listeners:listeners,
listen:listen
}
/*
ES6簡寫
減少代碼重複讀,增加可讀性
*/
var listeners = []
function listen(){
}
var events = {listeners , listen}
/*
可計算的屬性名
*/
//原寫法
var expertise = 'journalism'
var person = {
name:"Sharon",
age:27
}
person[expertise] = {
years:5,
interests:['international' , 'politics' , 'internet']
}
/*
ES6寫法
對象字面量可以使用計算屬性名,把任何表達式放在中括號裏,
表達式的運算結果將會是對應的屬性名
*/
var expertise = 'journalism'
var person = {
name:"Sharon",
age:27,
[expertise]:{
years:5,
interests:['international','politics','internet']
}
}
/*
注意:
簡寫屬性和計算屬性名不可以同時試用。
簡寫屬性是一種編譯階段生效的語法糖
計算的屬性名在運行時才生效
兩者混用會報錯,降低可讀性
下面是錯誤寫法:
var expertise = 'journalism'
var journalism = {
years: 5,
interests: ['international', 'politics', 'internet']
}
var person = {
name: 'Sharon',
age: 27,
[expertise] // 這裏會報語法錯誤
}
*/
/*
下面這種情況,可計算的屬性名可以讓代碼更簡潔
eg:某個新對象的屬性引自另一個對象:
*/
var grocery = {
id:'bananas',
name:'Bananas',
units:6,
price:10,
currency:'USD'
}
var groceries = {
[grocery.id]:grocery
}
/*
需要構建的對象的屬性名來自函數參數,
如果在es5處理,需要先聲明一個對象字面量
再動態的添加屬性,再返回這個對象
*/
//es5
function getEnvelope(type,description){
var envelope = {
data:{}
}
envelope[type] = description
return envelope
}
//es6提供的利用計算屬性名,簡潔寫法如下:
function getEnvelope(type,description){
return{
data:{},
[type]:description
}
}
/*
方法定義
傳統定義對象方法的方式,以下代碼構建了一個事件發生器
其中的on方法用以註冊時間,emit方法用以執行事件
*/
var emitter = {
events:{},
on:function (type,fn){
if(this.events[type] === undefined){
this.events[type] = []
}
this.events[type].push(fn)
},
emit:function(type,event){
if(this.events[type] === undefined){
return
}
this.events[type].forEach(function(fn){
fn(event)
})
}
}
/*
ES6的對象字面量方法簡寫允許我們省略function關鍵字
以及之後的冒號
*/
var emitter = {
events:{},
on(type,fn){
if(this.events[type] === undefined){
this.events[type] = []
}
this.events[type].push(fn)
},
emit(type,event){
if(this.events[type] === undefined){
return
}
this.events[type].forEach(function(fn){
fn(event)
})
}
}
/*
箭頭函數
不需function關鍵字,參數和函數體之間用=>相連
與匿名函數的不同點:
箭頭函數不能被直接命名,不過允許他們賦值給一個變量
箭頭函數不能用作構造函數,你不能對箭頭函數試用new關鍵字
箭頭函數沒有prototype屬性
箭頭函數綁定了詞法作用域,不會修改this的指向
下面是箭頭函數的最大特點:
我們在箭頭函數的函數體內試用this,arguments,super
等都指向包含箭頭函數的上下文,箭頭函數本身不產生新
的上下文,下述代碼中,我們創建了一個名爲timer的對
象,他的屬性seconds用以計時,方法start用以開始計
時,若我們在若干秒後調用start方法,將打印出當前的
seconds值
*/
//ES5
var timer = {
seconds:0,
start(){
setInterval(function(){
this.seconds++
},1000)
}
}
timer.start()
setTimeout(function(){
console.log(timer.seconds)
},3500)
/* >0
解析:
start中的this指向window
console輸出undefined
所以調用的時候3.5秒後輸出的seconds還是0
如需要改寫可以向start(){}中添加
var that = this ,將下面的this改爲that
即可輸出3,
ES6不會出現這種指向性的情況:
*/
var tiemr = {
seconds:0,
start(){
setInterval(()=>{
this.seconds++
})
}
}
timer.start()
setTimeout(function(){
console.log(timer.seconds)
},3500)
/*
由於不存在指向性問題,所以輸出正確值3
箭頭函數的作用域不能通過.call,.apply,.bind等語法
改變,這使得箭頭函數的上下文永久不變,
再來幾個例子:
*/
function puzzle(){
return function(){
console.log(arguments)
}
}
puzzle('a','b','c')(1,2,3)
//1,2,3 因爲對於匿名函數而言,arguments指向本身
function puzzle(){
return ()=>{
console.log(arguments)
}
}
puzzle('a','b','c')(1,2,3)
//a,b,c 箭頭函數的特殊性決定其本身沒有arguments對象,這裏的是其父函數puzzle的
/*
簡寫的箭頭函數
*/
var example = (parameters) => {
//函數體
}
/*
簡寫1
當只有一個參數的時候,我們可以省略箭頭函數參數兩側的括號
*/
var doublue = value => {
return value * 2
}
/*
簡寫2
對只有單行表達式並且該表達式的值爲返回值的箭頭函數,
{}可以省略,return可以省略
*/
var double = (value) => value*2
/*
簡寫3
合併使用
*/
var double = value => value*2
/*
簡寫箭頭函數帶來的問題
當你簡寫箭頭函數返回值爲一個對象的時候,你需要用
小括號來擴起你想返回的對象,否則瀏覽器會把對象的
{}解析爲箭頭函數函數體的開始結束標記
下面是正確的簡寫形式
*/
var objectFactory = () => ({modular:"es6"})
/*
下面是錯誤的形式
箭頭函數會把本想返回的對象的花括號解析爲函數體
number被解析爲label,value解釋爲沒有做任何事
情表達式,而且沒有顯式的試用return,返回值默認
是undefined
*/
[1,2,3].map(value => {number:value})
/*[undefined,undefined,undefined]
當我們返回的對象字面量不止一個屬性的時候,
瀏覽器編譯器不能正確解析第二個屬性,這時
會拋出語法錯誤
*/
[1,2,3].map(value=>{number:value,verfied:true})
//解決 把返回的對象字面量博鰲國在小括號中,幫助瀏覽器正確解析
[1,2,3].map(value=>({number:value,verfied:true}))
/*
[{ number: 1, verified: true },
{ number: 2, verified: true },
{ number: 3, verified: true }]
*/
/*
該何時試用箭頭函數
箭頭函數並非適用於所有的情況,比如說,對於一個行數
很多的複雜函數,試用=>代替function關鍵字帶來的簡潔
性並不明顯,箭頭函數不能直接命名,但是可以通過賦值給
變量的形式實現間接命名,如下代碼中,我們把箭頭函數賦值
給變量throwError,當函數被調用時,會拋出錯誤,這個時候
可以追溯到是箭頭函數throwError報的錯
*/
var throwError = message => {
throw new Error(message)
}
throwError('this is a warning')
/*
error:this is a warning
如果你想完全控制你函數中的this,
使用箭頭函數是簡潔高效的,採用
函數式變成尤其如此
*/
[1,2,3,4]
.map(value => value * 2)
.filter(value => value >2)
.forEach(value => console.log(value))
/*
4
6
8
*/
/*
解構賦值
ES6提供的最靈活和富於表現性的新特徵最莫過於解構,
某種程度上解構可以看做是變量賦值的語法糖,可以
應用於對象,數組深知函數的參數。
1.對象解構
爲了更好的描述對象解構如何使用,我們先構建下面
這樣一個對象:
*/
//描述Bruce Wayne的對象
var character = {
name:"Bruce",
pseudonym:"Batman",
metadata:{
age:34,
gender:'male'
},
batarang:['gas pellet' , 'bat-mobile control' , 'bat-cuffs']
}
/*
假如現在有一個名爲pseudonym的變量,我們
想讓其變量值指向character.pseudonym,
使用es5:
*/
var pseudonym = character.pseudonym
//ES6致力於讓我們的代碼更簡潔,通過ES6我們可以用這段代碼實現同樣功能:
var { pseudonym } = character
//如同你可以使用var加逗號在一行中同時聲明多個變量,解構的花括號內也可以做:
var { pseudonym , name } = character
//還可以混用解構和常規的自定義變量,這也是解構語法靈活性的表現之一
var { pseudonym } = character , two = 2
//解構允許我們使用別名,如果我們想把character.pesudontm賦值給變量alias,可以這樣
var { pseudonym : alias } = character
//對於多層解構,也可以賦予別名,可以通過非常簡潔的方法修改子屬性名稱:
var { metadata:{ gender:characterGender } } = character
//ES5中,調用未曾生聲明的值,你會得到undefined
console.log(character.boots)
console.log(character['boots'])
//都是undefined,使用解構,情況也是類似的
var { boots } = character
console.log(boots)
//對於多層結構,boots不存在與character中,這時程序會拋出異常,好比調用undefined和null
var { boots:{size} } = character
var { missing } = null
//解構其實就是一種語法糖,下面這段代碼幫助理解
var nothing = null
var missing = nothing.missing
//結構可以添加默認值,如果右側不存在對應的值,默認值生效,默認值可以是數值,字符串,函數,對象,也可以是某一個存在的變量:
var { boots = { size : 10 } } = character
console.log(boots)
//對於多層結構,同樣可以使用默認值
var { metadata:{ enemy = 'Satan' } } = character
console.log(enemy)
//默認值和別名也可以一起使用,不過要注意別名要放在前面
var { boots:footwear = {size:10} } = character
//對象解構支持計算屬性名,這個時候必須添加別名,這是因爲計算屬性名允許任何類型表達式
//不添加別名瀏覽器解析的時候會出問題
var {['boo' + 'ts']:characterBoots} = character
/*不是在任何情況下都應該使用結構,語句characterBoots = character[type]
看起來比{[type]:charaterBoots} = character語義更清晰
但是如果你需要提取對象中的子對象,結構就更加方便
*/