zoukankan      html  css  js  c++  java
  • ES5严格模式(Strict mode)(转)

    ES5严格模式(Strict mode)

    https://www.cnblogs.com/snandy/p/3428171.html

    严格模式(Strict mode)是由ECMA-262规范定义的新兴JavaScript标准,第五版发布于2009年12月。旨在改善错误检查功能并且标识可能不会延续到未来JavaScript版本的脚本。ES5严格模式是限制性更强的JavaScript变体,它与常规JavaScript的语义不同,其分析更为严格。

    目前,除了IE6-9,其它浏览器均已支持ES5严格模式。

    一、严格模式的使用

    严格模式的使用很简单,只有在代码首部加入字符串  "use strict"。有两种应用场景,一种是全局模式,一种是局部模式。

    1)全局模式

    1
    2
    3
    'use strict'
    var globalVal = 100
    console.log(globalVal)

    执行后输出了100,与非严格模式没什么区别。

    2)局部模式

    将"use strict"放到函数内的第一行,如下

    1
    2
    3
    4
    5
    6
    function func() {
        'use strict'
        var localVal = 200
        console.log(localVal)
    }
    func()

    执行后输出了200,与非严格模式也没用什么区别。

    3)模块模式

    如果你想定义一个模块或者一个小库,自然采用一个匿名函数自执行是不错的选择

    1
    2
    3
    4
    5
    ~function() {
        "use strict";
          
        // Define your library strictly...
    }();

    “use strict” 的位置是很讲究的,必须在首部。首部指其前面没有任何有效js代码。以下都是无效的,将不会触发严格模式。

    a)“use strict” 前有代码

    1
    2
    3
    var width = 10
    'use strict'
    globalVar = 100

    b)“use strict” 前有个空语句都不行

    1
    2
    3
    ;
    'use strict'
    globalVar = 100

    1
    2
    3
    4
    5
    function func() {
        ;
        'use strict'
        localVar = 200
    }

    1
    2
    3
    4
    function func() {
        ;'use strict'
        localVar = 200
    }

      

    当然,“use strict”前加注释是可以的

    1
    2
    3
    // strict mode
    'use strict'
    globalVar = 100

    1
    2
    3
    4
    5
    6
    function func() {
        // strict mode
        'use strict'
        localVar = 200
    }
    func()

    二、严格模式下的执行限制

    上面举的两个例子,在严格模式中输出与普通模式没用什么区别。下面就不一样了。

    1)不使用var声明变量严格模式中将不通过

    我们知道JS是弱类型,宽松的语言。不使用var声明的变量默认转为全局变量。但在严格模式中将不允许,会报语法错误。

    1
    2
    'use strict'
    globalVal = 100

    执行,Firebug提示如下

    又如全局的for循环

    1
    2
    3
    4
    'use strict'
    for (i=0; i<5; i++) {
        console.log(i)
    }

    这种写法在非严格模式中很危险,i 会不小心溢出成为全局变量。但在严格模式中会报错

    局部模式

    1
    2
    3
    4
    5
    6
    function func() {
        'use strict'
        localVal = 200
        console.log(localVal)
    }
    func()

    执行,Firebug报错

    因此,严格模式中声明变量务必记得加一个var。

    2)任何使用'eval'的操作都会被禁止

    1
    2
    3
    4
    5
    6
    7
    8
    9
    'use strict'
    var obj = {}
    var eval = 3
    obj.eval = 1
    obj.a = eval
    for (var eval in obj) {}
    function eval() {}
    function func(eval) {}
    var func = new Function('eval')

    Firebug报错

    3)eval作用域

    JS中作用域有两种,全局作用域和函数作用域。严格模式带来了第三种作用域:eval作用域,如下

    1
    2
    3
    4
    'use strict'
    var a = 10
    eval('var a = 20; console.log(a)')
    console.log(a)

    Firebug控制台依次输出了20,10。eval是在全局模式下(非函数内)的,如果不加严格模式,此时修改的是全局的a。即输出20,20。见 eval与window.eval的差别

    4)with被禁用

    1
    2
    3
    4
    'use strict'
    with({a:1}) {
         
    }

    Firebug报错

    5)caller/callee 被禁用

    1
    2
    3
    4
    5
    6
    function func() {
        'use strict'
        arguments.callee
        arguments.caller
    }
    func()

    Firebug报错

    6)对禁止扩展的对象添加新属性会报错

    1
    2
    3
    4
    'use strict'
    var obj = {}
    Object.preventExtensions(obj)
    obj.a = 1 // 报错

    Firebug报错

    7)删除系统内置的属性会报错

    1
    2
    3
    'use strict'
    delete Object.prototype    // 报错
    delete Function.prototype // 报错

    Firebug 报错

    8)delete使用var声明的变量或挂在window上的变量报错

    1
    2
    3
    4
    5
    'use strict'
    var obj = {a:1}
    window.a = 1
    delete obj // 报错
    delete a   // 报错

    Firebug报错

    9)delete不可删除属性(isSealed或isFrozen)的对象时报错

    1
    2
    3
    4
    'use strict'
    var obj = {a: 1}
    Object.seal(obj)
    delete obj.a

    Firebug报错

    10)对一个对象的只读属性进行赋值将报错

    1
    2
    3
    4
    'use strict'
    var obj = {}
    Object.defineProperty(obj, 'a', {value: 1, writable: false})
    obj.a = 2 // 报错

    Firebug报错

    11)对象有重名的属性将报错

    1
    2
    3
    4
    5
    'use strict'
    var obj = {
        a: 1,
        a: 2
    }

    Firebug报错

    而在非严格模式中,后面的属性将覆盖前面的属性,即obj.a等于2。

    12)函数有重名的参数将报错

    1
    2
    3
    4
    5
    'use strict'
    function func(a, a) {
        alert(a)
    }
    func()

    Firebug报错

    而在非严格模式中,后面的同名参数将覆盖前面的。

    13)八进制表示法被禁用

    1
    2
    'use strict'
    var num = 022

    Firebug报错

    14)arguments严格定义为参数,不再与形参绑定

    先看非严格模式代码

    1
    2
    3
    4
    5
    function func(a) {
        arguments[0] = 2
        alert(a) // 2
    }  
    func(1)

    func调用时传参为1,函数内部通过arguments修改为2,此时alert的为修改后的2。 而在严格模式中则不能被修改,如下

    1
    2
    3
    4
    5
    6
    'use strict'
    function func(a) {
        arguments[0] = 2
        alert(a) // 1
    }  
    func(1)

    显示的严格的为传入的1。

    其实有点还有点复杂,如果alert的是arguments[0],实际在严格模式中仍然被修改为2了。如下

    1
    2
    3
    4
    5
    6
    'use strict'
    function func(a) {
        arguments[0] = 2
        alert(arguments[0]) // 2
    }  
    func(1)

    可以参考下 仅Chrome中函数实参与形参发生关联

    15)函数必须声明在顶层

    我们知道函数声明和函数表达式是两个不同的概念。一般函数声明都在最顶层,ES5前的JS宽松,你可以写在if或for内(强烈鄙视这种写法)。当然Firefox的解析方式与其他浏览器不同,见SJ9002。而在严格模式中这些写法将直接报错

    1
    2
    3
    4
    5
    6
    7
    'use strict'
    if (true) {
        function func1() { } // 语法错误
    }
    for (var i = 0; i < 5; i++) {
        function func2() { } // 语法错误
    }

    Firebug报错

    16)ES5里新增的关键字不能当做变量标示符使用,如implements, interface, let, package, private, protected, public, static, yield

    1
    2
    3
    'use strict'
    var let = 10
    var yield = 20

    Firebug报错

    17)call/apply的第一个参数直接传入不包装为对象

    1
    2
    3
    4
    5
    6
    'use strict'
    function func() {
        console.log(typeof this)
    }
    func.call('abcd'// string
    func.apply(1)     // number

    Firebug输出如下

    依次为"string","number"。而在非严格模式中call/apply将对值类型的"abcd",1包装为对象后传入,即两次输出都为"object"。

    18)call/apply的第一个参数为null/undefined时,this为null/undefined

    这里以call来示例

    1
    2
    3
    4
    5
    6
    'use strict'
    function func() {
        console.log(this)
    }
    func.call(undefined) // undefined
    func.call(null)      // null

    Firebug输出如下

    依次是undefined,null。而非严格模式中则是宿主对象,浏览器里是window,node.js环境则是global。

    19)bind的第一个参数为null/undefined时,this为null/undefined

    bind是ES5给Function.prototype新增的一个方法,它和call/apply一样在function上直接调用。它返回一个指定了上下文和参数的函数。当它的第一个参数为null/undefined时,情形和call/apply一样,this也为null/undefined。

    1
    2
    3
    4
    5
    6
    7
    8
    'use strict'
    function func() {
        console.log(this)
    }
    var f1 = func.bind(null)
    var f2 = func.bind(undefined)
    f1() // null
    f2() // undefined

    而在非严格模式中输出的都是window(或global)。

    相关:

    Mozilla strict mode

    http://msdn.microsoft.com/library/br230269.aspx

    http://java-script.limewebs.com/strictMode/test_hosted.html

    http://dmitrysoshnikov.com/ecmascript/es5-chapter-2-strict-mode/

    http://javascriptweblog.wordpress.com/2011/05/03/javascript-strict-mode/

    JavaScript中delete操作符不能删除的对象

     
    分类: ECMAScript
    好文要顶 关注我 收藏该文  
    9
    0
     
     
     

    仅Chrome中函数实参与形参发生关联

    Chrome中也有不少 Bug ,但更新修复速度极快。下面又发现一个有趣的现象函数实参与形参发生了关联。

    1
    2
    3
    4
    5
    6
    function func(x,y){
        //alert(x);
        arguments[1] = 5;
        alert(y); // --> 5
    }  
    func(3);

    IE6/7/8/9,Firefox,Safari, Opera中 y 弹出为undefined,Chrome 则为5。

    函数func定义了形参x,y;调用时实参为3。func内部修改了实参arguments[1],非Chrome浏览器中形参y不会与arguments[1]关联,即为undefined。Chrome则相反,修改arguments[1]同时即修改了形参y。


    修改形参y,实参arguments[1]在Chrome中同样被修改,即相互关联。

    1
    2
    3
    4
    5
    6
    function func(x,y){
        //alert(x);
        y = 6;
        alert(arguments[1]); // --> 6
    }  
    func(3);

    2012-10-23:Chrome22测试,已不存在这个问题。重新总结如下:

    1,调用时实参与定义时形参数量一致时,实参与arguments互相影响,修改其中的一个其对应的也会被修改。

    2,实参与形参数量不一致时,不关联,不互相影响。

     
     
    « 上一篇: 搜狗输入法使用记录
    » 下一篇: JavaScript中的不可见数据类型
  • 相关阅读:
    WCF、Net remoting、Web service概念及区别
    新浪微博技术架构分析
    谈SOA和云的分层架构
    开发人员眼中最好的代码编辑器是什么?
    调试脚本,远离alert
    struts2与cookie实现自动登录和验证码验证
    把旧的项目改变名称重新部署到tomcat下发现项目名称还是原来的项目名称,解决方案
    myeclipse2014 安装maven3.3.9和mave配置本地仓库
    mysql在表的某一位置增加一列、删除一列、修改列名
    Java实现对cookie的增删改查
  • 原文地址:https://www.cnblogs.com/yasepix/p/11858277.html
Copyright © 2011-2022 走看看