ES6——let和const

  這裏主要介紹let和const的使用方法閉包

  介紹兩種新的聲明對象的方法以前,先介紹ES6中新增的塊級做用域app

塊級做用域

  能夠簡單理解爲,用一對花括號括起來的區域即爲塊級做用域,例如forifswitch裏的花括號,能夠嵌套ide

  若是在全局環境下,默認也是一個塊級做用域,不過這個塊比較特殊,也就是不存在離開塊級做用域的問題函數

  但建立對象時的一對花括號不算塊級做用域spa

  

  子級塊級做用域能夠訪問到父級塊級做用域中的變量3d

  

   特別注意,for語句中的()也是一個塊級做用域,然後面的{}則是()的子級塊級做用域code

  也就是說,能夠在for語句的執行語句塊中,訪問到for語句()裏用let聲明的變量,而出了for語句則沒法訪問該變量對象

  

 

let

  上面也介紹了一些let的使用方法特點,即:blog

  1.做用於塊級做用域中遞歸

  2.能夠被嵌套於其內部的子級的塊級做用域訪問到

  此外,let和var兩種聲明方式還有如下的區別:

同一做用域中不可重複聲明

  使用var能夠在同一塊級做用域屢次聲明同名的變量,且再次聲明不賦值時,變量的值不變

  而使用let,只能夠在同一塊級做用域中聲明一次同名變量,再次聲明就會報錯,在不一樣的塊級做用域中不存在該問題

  let聲明後沒有賦值,默認該變量值爲undefined

  

沒有變量提高(不會被預解析)

  let聲明的變量不會被有聲明提早的現象,必須在聲明後再調用,不然報錯

  

暫存死區

  ES6中,let聲明的同名變量在聲明時產生一個封閉的做用域,其如下的子級塊級做用域沒法訪問到該變量,這個現象即暫存死區

  

小案例

  能夠利用let聲明的塊級做用域,形成和閉包一樣的效果

for(let i=1;i<=10;i++){
    var btn = document.createElement("button");
    btn.innerText = i;
    btn.onclick = function(){
        console.log(i);
    }
    document.body.appendChild(btn);
}
let聲明和按鈕點擊

 

const

  ES6中新增的另外一種聲明方法爲const,能夠用來聲明常量

  這裏的常量若是是基本類型,其值聲明後不可改變

  若是是引用類型,則能夠修改內部的屬性方法,只要不修改其變量名指向的引用類型地址便可

  

  此外,const還和let有衆多相同的特性,例如:

  1.同一塊級做用域中,不可重複聲明

  2.沒有變量提高(沒有預解析)

  3.只在當前的塊級做用域中能夠被訪問到

引用類型屬性修改問題

  若是用const聲明引用類型,其屬性值是能夠改變甚至添加的

  若是不但願屬性值和屬性名改變,也不但願擴充新的屬性名和屬性值,須要用Object.freeze()方法

  

 

ES6以前聲明常量的方法

  ES6中提供了const來聲明常量,那ES6以前又是如何聲明常量的呢?

Object對象的seal方法

  Object對象的seal方法,可讓聲明過的對象沒法擴展,即沒法添加新的屬性/方法,但能夠修改已有的屬性值

  

Object對象的defineProperty方法

  defineProperty方法能夠傳入三個參數:要修改的對象,要修改的屬性名,要修改的屬性值

  其中要修改的屬性值能夠設置其value()以及writable(是否可寫),注意writable的屬性設置是不可逆的(即後續沒法再次從新設置)

  

  綜上能夠發現,Object對象的seal方法和defineProperty方法加起來才實現freeze方法(即對象屬性不可擴展,同時對象屬性不可更改)

  

 小案例

  用以上的seal和defineProperty方法,來封裝一個同freeze功能相同的方法

  注意這裏須要考慮到對象內部嵌套對象的可能性,須要用遞歸

//模擬freeze方法
//思路:傳入一個對象,先遍歷對象中的全部屬性,讓其每一個屬性的written都變成false
//最後對整個對象用seal方法,讓對象不可擴展
function frozen(obj){
    //遍歷整個對象
    for(let i in obj){
        //若是該屬性值是對象,用遞歸,繼續讓其沒法擴展和沒法修改
        //修復函數類型能夠被修改的bug
        if(obj[i] instanceof Object && typeof obj[i] != "function"){
            frozen(obj[i]);
        }
        //若是屬性值不是對象,則設置其不可更改
        else{
            //須要明確屬性值不是原型鏈上的
            if(obj.hasOwnProperty(i)){
                Object.defineProperty(obj,i,{
                    writable:false
                })
            }
        }
    }
    //最後對整個對象用seal讓其不可擴展
    Object.seal(obj);
}

var xm = {
    age:18,
    name:"xiaoming",
    language:{
        chinese:"fluent",
        english:"master"
    },
    say:function(){
        console.log("hello");
    }
}
frozen(xm);
相關文章
相關標籤/搜索