ECMA Script 6_必需要知道的基礎

ES6 爲了保持兼容性,var 命令和 function 命令聲明的全局變量,依舊是頂層對象的屬性;es6

另外一方面規定,let 命令、const 命令、class 命令聲明的全局變量,不屬於 window 的屬性。瀏覽器

也就是說,從ES6開始,全局變量將逐步與頂層對象的屬性脫鉤安全

瀏覽器頂層對象指的是 window 對象ide

Node頂層對象指的是 global 對象,但其餘環境都不支持函數

window 對象應該有實體含義,指的是瀏覽器的窗口對象ui

 

爲了可以在各類環境,都能取到頂層對象,如今通常是使用 this變量。this

全局環境中,this 會返回頂層對象。可是,Node 模塊和 ES6 模塊中,this 返回的是當前模塊。
函數裏面的 this,若是函數不是做爲對象的方法運行,而是單純做爲函數運行,this 會指向頂層對象。
可是,嚴格模式下,這時 this 會返回 undefined。
無論是嚴格模式,仍是普通模式,new Function('return this')(),老是會返回全局對象。
可是,若是瀏覽器用了CSP(Content Security Policy,內容安全政策),那麼 eval、new Function 這些方法均可能沒法使用。spa

綜上所述,很難找到一種方法,能夠在全部狀況下,都取到頂層對象。下面是勉強能夠使用的方法code

  • var getGod = function () {
        if (typeof global !== 'undefined'){
            return global;
        };
        if (typeof window !== 'undefined'){
            return window;
        };
        if (typeof self !== 'undefined'){
            return self;
        };
        throw new Error('unable to locate global object');
    };
    
    var God = getGod();

如今有一個提案,在語言標準的層面,引入global做爲頂層對象。對象

也就是說,在全部環境下,global都是存在的,均可以從它拿到頂層對象。

墊片庫system.global模擬了這個提案,能夠在全部環境拿到global

  •  // CommonJS的寫法
    var global = require('system.global')();
    
    // ES6模塊的寫法
    import getGlobal from 'system.global';
    const global = getGlobal();

參考: http://es6.ruanyifeng.com/#docs/let

ES6 聲明變量的六種方法

  • var v = 0;
  • function myyFunc(){};
  • let   l = 0;
  • const c = 0;
  • import
  • class

let age = 22;

  • 聲明一個變量
  • 不會被預處理,不存在聲明提高        
  • 不能重複聲明            // Identifier 'a' has already been declared
  • // 報錯
    function () {
        let a = 10;
        var a = 1;
    }
    
    // 報錯
    function () {
        let a = 10;
        let a = 1;
    }
    
    function func(arg) {
        let arg;    // 報錯
    }
    
    function func(arg) {
        {
            let arg; // 不報錯
        }
    }

做用域

  • 全局做用域
  • 函數做用域
  • 塊做用域            letconst 關鍵字定義的 變量 和 常量,function 關鍵字定義的函數        都存在塊做用域
  • "use strict";
    if (true) { var v = 0; let l = 0; const c = 0; function f() { console.log('I am inside!'); }; }; console.log(v); // 0 console.log(l); // Uncaught ReferenceError: l is not defined console.log(c); // Uncaught ReferenceError: c is not defined f(); // Uncaught TypeError: f is not a function

     

  • 暫時性死區(Temporal Dead Zone,簡稱TDZ)

變量 x 使用 let 命令聲明,因此在聲明以前,都屬於x的「死區」,只要用到該變量就會報錯。

所以,typeof 運行時就會拋出一個 Reference Error。

做爲比較,若是一個變量根本沒有被聲明,使用 typeof 反而不會報錯

在沒有 let 以前,typeof 運算符是百分之百安全的,永遠不會報錯。有了 let ,如今這一點不成立了

  • 隱蔽的死區
  • window.addEventListener("DOMContentLoaded", function(){
         'use strict';function bar(x = y, y = 2) { return [x, y]; } console.log(bar(1, 2)); // 正常: let x=1; let y=2; console.log(bar()); // 報錯 let x=y; /* y 的變量死區 */ let y=2;
    }, false);

     

  • "暫時性死區" 也意味着 typeof 再也不是一個百分之百安全的操做
  • if(true){
        typeof x;    // Reference Error
        let x;
    }
  • 塊級做用域內 let 又聲明瞭一個局部變量 tmp,致使後者綁定這個塊級做用域,因此在 let 聲明變量前,對 tmp 賦值會報錯
  • var tmp = 123;
    
    if (true) {
        tmp = 'abc'; // Reference Error
        let tmp;     // 
    }
  • let a = 123;
    
    if(true){    // 塊做用域
        let a = 456;
    };
    
    console.log(a);    // 123
    /**************************/ for(){} for(var in ){} switch(x){} while(1){}
  • 實例
  • // 三個按鍵
    for(let i=0; i< btns.length; i++){
        btn[i].onclick = function(){
            alert(i+1);    // 每次按鍵都會打印本身的索引
        };
    };
    
    // let i =0
    
    // let i =1 
    
    // let i =2
  • 關於 for(let i=0; i<max; i++){};    // 必定要知道,let i=0;    屬於for 塊做用域
  • 好比 有三個按鍵 用 for 事件
  • /****
            <div id="test_box">
                <div></div>
                <div></div>
                <div></div>
            </div>
    ****/
    window.addEventListener("DOMContentLoaded", function(){
        'use strict';
        var divs = document.getElementById("test_box").getElementsByTagName("div");
        
        /* for(let i=0; i<divs.length; i++){ divs[i].onclick = function(){ console.log(i+1); }; };
        能夠理解成:    就至關於:    ****/
        
        function add1(){ let i=0; divs[i].onclick = function(){ console.log(i+1); // 1  }; }; function add2(){ let i=0; i += 1; divs[i].onclick = function(){ console.log(i+1); // 2  }; }; function add3(){ let i=0; i += 1; i += 1; divs[i].onclick = function(){ console.log(i+1); // 3  }; }; add1(); add2(); add3(); /**** 不能理解成下面這個樣子
            function addEvent(){
                let i=0;
                divs[i].onclick = function(){
                    console.log(i+1);    // 3
                };
                i += 1;
                divs[i].onclick = function(){
                    console.log(i+1);    // 3
                };
                i += 1;
                divs[i].onclick = function(){
                    console.log(i+1);    // 3
                };
            };
        ****/
    }, false);

const PI = 3.1415926;

聲明一個常量,不可被更改

不會被預處理,不存在聲明提高        

不能重複聲明            // Identifier 'a' has already been declared

  • 值得注意的是

在將一個 對象 聲明爲常量時,只能保證 這個常量永遠指向這個對象,而仍是可以操做這個對象的屬性

  • const foo = {};
    
    // 爲 foo 添加一個屬性,能夠成功
    foo.prop = 123;
    foo.prop // 123
    
    // 將 foo 指向另外一個對象,就會報錯
    foo = {}; // TypeError: "foo" is read-only

若是真的想 連對象的屬性都不可寫,則必須使用 Object.freeze()

除了將對象自己凍結,對象的屬性也應該凍結。

下面是一個將對象完全凍結的函數

  • function freezeObj(obj){
        Object.freeze(obj);
        Object.keys(obj).forEach(function(attr){
            if ( typeof obj[attr] === 'object' ) {
                freezeObj(obj[attr]);
            };
        });
    };
相關文章
相關標籤/搜索