ES6 为了保持兼容性,var 命令和 function 命令声明的全局变量,依旧是顶层对象的属性;

另一方面规定,let 命令、const 命令、class 命令声明的全局变量,不属于 window 的属性。

也就是说,从ES6开始,全局变量将逐步与顶层对象的属性脱钩

浏览器顶层对象指的是 window 对象

Node顶层对象指的是 global 对象,但其他环境都不支持

window 对象应该有实体含义,指的是浏览器的窗口对象

为了能够在各种环境,都能取到顶层对象,现在一般是使用 this变量。

全局环境中,this 会返回顶层对象。但是,Node 模块和 ES6 模块中,this 返回的是当前模块。
函数里面的 this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this 会指向顶层对象。
但是,严格模式下,这时 this 会返回 undefined。
不管是严格模式,还是普通模式,new Function('return this')(),总是会返回全局对象。
但是,如果浏览器用了CSP(Content Security Policy,内容安全政策),那么 eval、new Function 这些方法都可能无法使用。

综上所述,很难找到一种方法,可以在所有情况下,都取到顶层对象。下面是勉强可以使用的方法

  • 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); //
    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); //
    /**************************/
    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); //
    };
    }; function add2(){
    let i=0;
    i += 1;
    divs[i].onclick = function(){
    console.log(i+1); //
    };
    }; function add3(){
    let i=0;
    i += 1;
    i += 1;
    divs[i].onclick = function(){
    console.log(i+1); //
    };
    }; 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 // // 将 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]);
    };
    });
    };

ECMA Script 6_必须要知道的基础的更多相关文章

  1. ECMA Script 6_简单介绍

    ECMAScript 6 ECMA 组织 前身是 欧洲计算机制造商协会 指定和发布脚本语言规范,标准在每年的 6 月份正式发布一次,作为当年的正式版本 这样一来,就不需要以前的版本号了,只要用年份标记 ...

  2. ECMA Script 6_模块加载方案 ES6 Module 模块语法_import_export

    1. 模块加载方案 commonJS 背景: 历史上,JavaScript 一直没有模块(module)体系, 无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来. 其他语言都有这项功能: ...

  3. ECMA Script 6_数值的扩展

    1. 二进制 和 八进制 新的表示法 前缀 0b(或0B) 表示 二进制 前缀 0o(或 0O )表示 八进制 console.log(0b111110111 === 503); // true co ...

  4. ECMA Script 6_数组的扩展_扩展运算符

    1. 扩展运算符 内部调用的是数据结构的 Iterator 接口, 因此只要具有 Iterator 接口的对象,都可以使用扩展运算符 ... 如 map,,,, [...arr] 扩展运算符(spre ...

  5. ECMA Script 6_异步编程之 Promise

    Promise 对象 异步编程 方案,已同步的方式表达异步的代码,解决回调地狱的问题 比传统的解决方案——回调函数和事件——更合理和更强大 是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步 ...

  6. ECMA Script 6_解构赋值_模式匹配

    解构赋值 从数组中提取值,按照对应位置,对变量赋值 只要等号右边的值不是对象或数组,就先将其转为对象. 由于 undefined 和 null 无法转为对象,所以对它们进行解构赋值,都会报错 let ...

  7. ECMA Script 6_字符串_扩展_字符 是4字节还是2字节?_模板字符串

    ES6 字符串扩展 ES6 加强了对 Unicode 的支持,并且扩展了字符串对象 字符 的 Unicode 表示法 允许采用 \uxxxx 形式表示一个字符, 其中 xxxx 表示字符的 Unico ...

  8. ECMA Script 6_函数的扩展

    ES6规定只要函数参数使用了默认值.解构赋值.或者扩展运算符, 那么函数内部就不能显式设定为严格模式,否则会报错 1. 参数的默认值 ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面 函数 ...

  9. ECMA Script 6_对象的扩展

    对象 1. ES6 允许直接写入变量和函数,作为对象的属性和方法 const foo = 'bar'; /*****************属性的优化********************/ con ...

随机推荐

  1. [再寄小读者之数学篇](2014-06-22 发散级数 [中国科学技术大学2012年高等数学B考研试题])

    设 $a_n>0$, $S_n=a_1+a_2+\cdots+a_n$, 级数 $\dps{\vsm{n}a_n}$ 发散, 证明: $\dps{\vsm{n}\cfrac{a_n}{S_n}} ...

  2. [物理学与PDEs]第2章习题7 一维不可压理想流体的求解

    设有以 $x$ 轴为轴向的等轴截面管道, 其中充满着沿 $x$ 方向流动的不可压缩的理想流体, 在每一横截面上流体的状态相同, 且 $p=p(x)$. 若已知 $p(0) =p_1$, $p(L)=p ...

  3. 已知 $AB$, 求 $BA$

    设 $A,B$ 分别是 $3\times 2$ 和 $2\times 3$ 实矩阵. 若 $\dps{AB=\sex{\ba{ccc}  8&0&-4\\  -\frac{3}{2}& ...

  4. Vue-cli 模拟数据库

    vue-cli2.x 版本开发: 新版在build目录下的webpack.dev.conf.js配置本地数据访问: 1,在const portfinder = require(‘portfinder’ ...

  5. SpringBoot中Application开启与关闭

    0.声明 缘由:没有学过或者没有经历SpringBoot的Application运行机制的话,一定会好奇,博主为啥会写一篇关闭开启的博文,是不是好幼稚?(/o(╥﹏╥)o),待我娓娓道来......为 ...

  6. LOJ #2116 Luogu P3241「HNOI2015」开店

    好久没写数据结构了 来补一发 果然写的时候思路极其混乱.... LOJ #2116 Luogu P3241 题意 $ Q$次询问,求树上点的颜色在$ [L,R]$中的所有点到询问点的距离 强制在线 询 ...

  7. php 默认保几位小数,末尾为0去掉

    计算保留几位小数,末位为0舍去 // 计算 默认保留1位小数 protected function getSprintf($value,$count,$digit = 1) { $num = 0; i ...

  8. matplotlib中的plt.ion()和plt.ioff()函数

    转自https://blog.csdn.net/yzy__zju/article/details/85008603 Matplotlib的显示模式默认为阻塞(block)模式,因此若想动态显示图像,则 ...

  9. AGC电路以及AD8347正交解调芯片

    1.AGC电路的工作原理 1.1AGC电路的用途 随着电磁环境的日益恶化, 不同频段电磁信号之间的相互串扰, 以及可能出现的人为干扰, 将会导致接收机输入端口的信号动态范围较大, 一旦出现电路饱和或是 ...

  10. .Net三层架构

    .Net三层架构   希望朋友们留下自己对三层架构的理解... 三层体系结构的概念 用户界面表示层(USL) 业务逻辑层(BLL) 数据访问层(DAL) BLL将USL与DAL隔开了,并且加入了业务规 ...