ES6 對象簡寫 計算屬性 箭頭函數 對象解構

        //對象字面量
        /*
            以{}形式直接表示的對象
        */
       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語義更清晰
但是如果你需要提取對象中的子對象,結構就更加方便
*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章