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]);
            };
        });
    };
相关文章
相关标签/搜索