组团学

ES5进阶-严格模式

阅读 (368)

一、了解严格模式

ECMAScript 5的严格模式是采用具有限制性JavaScript变体的一种方式,从而使代码显示地 脱离“马虎模式/稀松模式/懒散模式“(sloppy)模式。严格模式指的是使js在更为严格的条件下运行。严格模式的主要作用是规范我们写代码习惯,以及为js升级做好铺垫

为什么使用严格模式:

  1. 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为
  2. 增加更多报错的场合,消除代码运行的一些不安全之处,保证代码运行的安全
  3. 提高编译器效率,增加运行速度
  4. 为未来新版本的Javascript做好铺垫
  5. "严格模式"体现了Javascript更合理、更安全、更严谨的发展方向,包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱它

注意:同样的代码,在"严格模式"中,可能会有不一样的运行结果;一些在"正常模式"下可以运行的语句,在"严格模式"下将不能运行。掌握这些内容,有助于更细致深入地理解Javascript,让你变成一个更好的程序员

调用严格模式

严格模式可以应用到整个脚本或个别函数中。不要在封闭大括弧 {} 内这样做,在这样的上下文中这么做是没有效果的。在 evalFunction 、内联事件处理属性、 WindowTimers.setTimeout() 方法中传入的脚本字符串,其行为类似于开启了严格模式的一个单独脚本,它们会如预期一样工作

  • 为脚本开启严格模式

    为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句 "use strict";'use strict';

    // 整个脚本都开启严格模式的语法 "use strict"; var v = "Hi! I'm a strict mode script!"; console.log(v);

    这种语法存在陷阱,有一个大型网站已经被它坑倒了,不能盲目的合并冲突代码。试想合并一个严格模式的脚本和一个非严格模式的脚本,合并后的脚本代码看起来是严格模式。反之亦然,非严格合并严格看起来是非严格的。合并均为严格模式的脚本或均为非严格模式的都没问题,只有在合并严格模式与非严格模式有可能有问题。建议按一个个函数去开启严格模式(至少在学习的过渡期要这样做)

    也可以将整个脚本的内容用一个函数包括起来,然后在这个外部函数中使用严格模式。这样做就可以消除合并的问题,但是这就意味着必须要在函数作用域外声明一个全局变量

  • 为函数开启严格模式

    function fnStrict(){ "use strict" var v = "Hi! I'm a strict function script!" console.log(v) } fnStrict() function noStrict(){ t = "Hi! I'm not a strict function script!" console.log(t) } noStrict()

浏览器的严格模式

主流浏览器现在实现了严格模式。但是不要盲目的依赖它,因为市场上仍然有大量的浏览器版本只部分支持严格模式或者根本就不支持(比如IE10之前的版本)。严格模式改变了语义。依赖这些改变可能会导致没有实现严格模式的浏览器中出现问题或者错误。谨慎地使用严格模式,通过检测相关代码的功能保证严格模式不出问题。最后,记得在支持或者不支持严格模式的浏览器中测试你的代码。如果你只在不支持严格模式的浏览器中测试,那么在支持的浏览器中就很有可能出问题,反之亦然

二、严格模式的限制

  • 不允许使用未声明的变量

    "use strict"; x = 3.14; // 报错 (x 未定义)
  • 对象也是一个变量

    "use strict"; x = {p1:10, p2:20}; // 报错 (x 未定义)
  • 不允许删除变量或对象

    "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; // 报错
  • 不允许对一个使用getter方法读取的属性进行赋值

    "use strict"; var obj = {get x() {return 0} }; obj.x = 3.14; // 报错
  • 不允许删除一个不允许删除的属性

    "use strict"; delete Object.prototype; // 报错
  • 变量名不能使用 “eval” 字符串

    "use strict"; var eval = 3.14; // 报错
  • 变量名不能使用 “arguments” 字符串

    "use strict"; var arguments = 3.14; // 报错
  • 不允许使用with这种语句

    "use strict"; with (Math){x = cos(2)}; // 报错
  • 由于一些安全原因,在作用域 eval() 创建的变量不能被调用

    // "use strict"; eval("var x = 2"); alert(x); // 报错
  • 禁止this关键字指向全局对象

    function f1(){ console.log(this) } f1() // "this"指向全局对象 function f2(){ "use strict"; console.log(this) } f2() // 因为严格模式下,this的值为undefined

    因此,使用构造函数时,如果忘了加new,this不再指向全局对象,而是报错

    function f(){ "use strict"; this.a = 1; }; f(); // 报错,this未定义
  • 保留关键字

    为了向将来Javascript的新版本过渡,严格模式新增了一些保留关键字

    • implements
    • interface
    • let
    • package
    • private
    • protected
    • public
    • static
    • yield
    "use strict"; var public = 1500; // 报错
需要 登录 才可以提问哦