• home > webfront > ECMAS > emphasis >

    ECMAScript进化史(2):​Web2.0时代的JavaScript1.5到ES5

    Author:[email protected] Date:

    2009年,ES5横空出世,JSer的春天到来。ES5相比十年前的JS1 5,带来哪些新特性呢? "严格模式 "体现了Javascript更合理、更安全、更严谨的发展方向。数组扩展了更多的方法,bind可以异步绑定this,Object新增方法,可以监听对象

    上篇介绍了JavaScript历史《ECMAScript进化史(1):话说Web脚本语言王者JavaScript的加冕历史》,我们知道

    2000年,JavaScript推出1.5版本,之后的9年(2000-2009),ES没有任何升级。期间的ES4居然被放弃了。具体原因博友们可以去查一下资料。直到2009年,ES5横空出世,同年,前端界也出了一个大事件——Node.js发布。Node.js是一个基于Google Chrome的V8引擎(2008年发布)的JS运行环境。这个时候,前端如雨后春笋,日新月异……所以,JavaScript1.5到ES5,专门开篇讲一遍。本篇主要讲ES5的新增补丁。

    strict严格模式

    除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode)。顾名思义,这种模式使得Javascript在更严格的条件下运行。所谓严格严格模式,其实就是限制一些用法,代码不能再那么飘逸了。有了锁链,JavaScript更加健壮。

    为什么使用严格模式:

    1. 消除代码运行的一些不安全之处,保证代码运行的安全;

    2. 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;

    3. 提高编译器效率,增加运行速度;

    4. 为未来新版本的Javascript做好铺垫。

    "严格模式"体现了Javascript更合理、更安全、更严谨的发展方向。下面是一些范例:

    "use strict";
     x = 3.14;   //报错 不允许使用未声明的变量或对象
     
     "use strict";
     var x = 3.14;
     delete x;   //报错 不允许删除变量或对象。
     
     "use strict";
     function x(p1, p2) {}; 
     delete x;  //报错 不允许删除函数。
     
     "use strict";
     function x(p1, p1) {};   // 报错 不允许变量重名
     
     "use strict";
     var x = 010; // 报错 不允许使用八进制
     
     "use strict";
     var x = \010; // 报错 不允许使用转义字符
     
     "use strict";
     var obj = {};
     Object.defineProperty(obj, "x", {value:0, writable:false});
     obj.x = 3.14; // 报错 不允许对只读属性赋值
     
     "use strict";
     var obj = {get x() {return 0} };
     obj.x = 3.14;            // 报错 不允许对一个使用getter方法读取的属性进行赋值
     
     "use strict";
     delete Object.prototype; // 报错 不允许删除一个不允许删除的属性
     
     "use strict";
     var eval = 3.14;         // 报错 变量名不能使用 "eval" 字符串:
     
     "use strict";
     var arguments = 3.14;    // 报错 变量名不能使用 "arguments"  字符串:
     
     "use strict";
     with (Math){x = cos(2)}; // 报错 不允许使用with
     
     "use strict";
     eval ("var x = 2");
     alert (x);               // 报错 由于一些安全原因,在作用域 eval() 创建的变量不能被调用:
     
     //禁止this关键字指向全局对象 
     function f(){
      return !this; // 返回false,因为"this"指向全局对象,"!this"就是false
     } 
     
     function f(){ 
      "use strict"; 
      return !this; // 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。
     }

    如何调用严格模式

    • 针对整个脚本文件:将"use strict"放在脚本文件的第一行,则整个脚本都将以"严格模式"运行。如果这行语句不在第一行,则无效,整个脚本以"正常模式"运行。如果不同模式的代码文件合并成一个文件,这一点需要特别注意。

      (严格地说,只要前面不是产生实际运行结果的语句,"use strict"可以不在第一行,比如直接跟在一个空的分号后面。)

    • 针对单个函数:将"use strict"放在函数体的第一行,则整个函数以"严格模式"运行。

    • 脚本文件的变通写法:因为第一种调用方法不利于文件合并,所以更好的做法是,借用第二种方法,将整个脚本文件放在一个立即执行的匿名函数之中。

    (function () {
        "use strict";
        // some code here
    })();

    针对ES5的推荐写法

    语法和行为改变

    • 全局变量显式声明:在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明

    • 静态绑定:Javascript语言的一个特点,就是允许"动态绑定",即某些属性和方法到底属于哪一个对象,不是在编译时确定的,而是在运行时(runtime)确定的。

      严格模式对动态绑定做了一些限制。某些情况下,只允许静态绑定。也就是说,属性和方法到底归属哪个对象,在编译阶段就确定。这样做有利于编译效率的提高,也使得代码更容易阅读,更少出现意外。

      具体来说,涉及以下几个方面。

      • 禁止使用with语句:因为with语句无法在编译时就确定,属性到底归属哪个对象。

      • 创设eval作用域:正常模式下,Javascript语言有两种变量作用域(scope):全局作用域和函数作用域。严格模式创设了第三种作用域:eval作用域。

        正常模式下,eval语句的作用域,取决于它处于全局作用域,还是处于函数作用域。严格模式下,eval语句本身就是一个作用域,不再能够生成全局变量了,它所生成的变量只能用于eval内部

    • 函数必须声明在顶层:将来Javascript的新版本会引入"块级作用域"。为了与新版本接轨,严格模式只允许在全局作用域或函数作用域的顶层声明函数。也就是说,不允许在非函数的代码块内声明函数。

    •  保留字增加:为了向将来Javascript的新版本过渡,严格模式新增了一些保留字:implements, interface, let, package, private, protected, public, static, yield

    • 增强的安全措施

      • 禁止this关键字指向全局对象

      • 禁止在函数内部遍历调用栈

    • 重名错误

      • 对象不能有重名的属性:正常模式下,如果对象有多个重名属性,最后赋值的那个属性会覆盖前面的值。严格模式下,这属于语法错误。

      • 函数不能有重名的参数:正常模式下,如果函数有多个重名的参数,可以用arguments[i]读取。严格模式下,这属于语法错误。

    •  arguments对象的限制:arguments是函数的参数对象,严格模式对它的使用做了限制。

      • 不允许对arguments赋值

      • arguments不再追踪参数的变化

      • 禁止使用arguments.callee

    • 禁止八进制表示法:正常模式下,整数的第一位如果是0,表示这是八进制数,比如0100等于十进制的64。严格模式禁止这种表示法,整数第一位为0,将报错。

    • 禁止删除变量

    • 显式报错

    数组新增方法

    ES5中新增了些数组方法,如下:

    1. forEach (js v1.6)

    2. map (js v1.6)

    3. filter (js v1.6)

    4. some (js v1.6)

    5. every (js v1.6)

    6. indexOf (js v1.6)

    7. lastIndexOf (js v1.6)

    8. reduce (js v1.8)

    9. reduceRight (js v1.8)

    这里推荐 张鑫旭的博客《ES5中新增的Array方法详细说明》,就不多说了。关于reduce的,安利下本站文章《js里reduce函数里面的坑!区分initialValue,previousValue,currentValue

    Function增加属性方法

    Function.prototype.bind();

    bind() 方法的主要作用就是将函数绑定至某个对象,bind()方法会创建一个函数,函数体内this对象的值会被绑定到传入bind() 函数的值。

    bind与 call/apply方法的区别

    共同点:都可以改变函数执行的上下文环境;

    不同点:bind: 不立即执行函数,一般用在异步调用和事件; call/apply: 立即执行函数。

    Date.now()

    Date.now方法返回当前时间距离时间零点(1970年1月1日 00:00:00 UTC)的毫秒数,相当于 Unix 时间戳乘以1000。es5新增

    Object方法

    • Object.setPrototypeOf、Object.getPrototypeOf、Object.create:为了语法的规范性,用Object.setPrototypeOf()(写操作)、Object.getPrototypeOf()(读操作) 、Object.create()(生成操作)替换原来对象proto属性

    • Object.keys:返回对象的可枚举属性和方法的名称,返回的结果添加到一个新的数组中

    • Object.getOwnPropertyNames:返回对象所有属性名称,并添加到数组中

    • Object.defineProperty:将属性添加到对象,或修改现有属性的特性

    • Object.getOwnPropertyDescriptor:获取指定对象的自身属性描述符。自身属性描述符是指直接在对象上定义(而非从对象的原型继承)的描述符。

      //实例
      var obj = {};
      // Add a data property.
      obj.newDataProperty = "abc";
      // Get the property descriptor.
      var descriptor = Object.getOwnPropertyDescriptor(obj, "newDataProperty");
      console.log(descriptor)// { value: 'abc', writable: true, enumerable: true, configurable: true }
    • Object.defineProperties:将一个或多个属性添加到对象,并/或修改现有属性的特性。

    • Object.preventExtensions / Object.isExtensible: 阻止向对象添加新属性

    • Object.seal / Object.isSealed:Object.seal(object);阻止修改现有属性的特性,并阻止添加新属性

      • 使对象不可扩展,这样便无法向其添加新属性。

      • 为对象的所有属性将 configurable 特性设置为 false。

    • Object.freeze / Object.isFrozen:阻止修改现有属性的特性和值,并阻止添加新属性

      • 为对象的所有属性将 configurable 特性设置为 false。在 configurable 为 false 时,无法更改属性的特性且无法删除属性。

      • 为对象的所有数据属性将 writable 特性设置为 false。当 writable 为 false 时,无法更改数据属性值。


    参考文章:

    - ES5中新增的Array方法详细说明 -张鑫旭

    - ES5总结 https://www.jianshu.com/p/febf41a8dc13

    - MDN, Strict mode
    - Dr. Axel Rauschmayer,JavaScript's strict mode: a summary
    - Douglas Crockford, Strict Mode Is Coming To Town




    转载本站文章《ECMAScript进化史(2):​Web2.0时代的JavaScript1.5到ES5》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/js6/2014_0213_214.html