• JS 严格模式和正常模式详解


    JavaScript 严格模式(Strict Mode)和正常模式(Non-Strict Mode)是用于控制 JavaScript 代码执行的两种不同模式。严格模式引入了一些限制和变化,旨在帮助开发人员编写更可靠、安全和高效的代码。在本文中,我们将详细探讨这两种模式的特点、区别和实例,以帮助您更好地理解它们。

    正常模式(Non-Strict Mode)

    正常模式是 JavaScript 的默认模式,它在早期版本的 JavaScript 中一直存在。在正常模式下,JavaScript 引擎执行代码时,不会进行额外的限制或错误检查。这意味着在正常模式下,开发人员可以编写更灵活的代码,但也容易引入一些潜在的错误和不安全的行为。

    下面是正常模式的一些特点:

    1.隐式全局变量:在正常模式下,未使用 var、let 或 const 声明的变量会被视为全局变量。这可能导致变量冲突和不可预测的行为。
    2.this 绑定松散:在正常模式下,全局对象的 this 值被视为全局对象自身。这可能导致意外的行为,特别是在函数内部。
    3.静默失败:在正常模式下,某些操作会导致静默失败,而不抛出错误。这可能导致开发人员难以诊断和调试问题。
    4.变量赋值的宽松规则:正常模式允许在不进行声明的情况下直接赋值给未声明的变量,这可能导致错误的变量名或拼写错误。
    5.不严格的语法解析:正常模式下,一些不规范的语法可能被接受,而在严格模式下将被拒绝。

    严格模式(Strict Mode)

    严格模式是 ECMAScript 5(ES5)中引入的一种更严格的模式,旨在减少常见的编程错误和提高代码质量。在严格模式下,JavaScript 引擎执行代码时会施加额外的限制和错误检查,从而提供更强大的代码分析和更多的运行时错误。

    下面是严格模式的一些特点:

    1.变量必须声明:在严格模式下,所有变量都必须使用 var、let 或 const 关键字进行声明,否则将抛出错误。这有助于避免意外的全局变量。
    2.this 绑定更严格:在严格模式下,函数内部的 this 值不会默认绑定到全局对象,而是为 undefined。这鼓励开发人员明确设置 this 值,减少不确定性。
    3.禁止删除变量:在严格模式下,使用 delete 操作符删除变量、函数和函数参数将导致错误。这有助于避免不必要的数据丢失和错误。
    4.禁止重复的参数:在严格模式下,函数不允许有重复的参数名,而在正常模式下,重复的参数名不会引发错误。
    5.禁止八进制字面量:在严格模式下,八进制字面量(如 0123)将导致错误。在正常模式下,它们将被解释为八进制数。
    6.禁止 this 关键字的赋值:在严格模式下,不允许对 this 关键字进行赋值。在正常模式下,这是有效的。
    7.保留字作为变量名:在严格模式下,一些保留字(如 arguments 和 eval)不能用作变量名。在正常模式下,这是允许的。
    8.禁止对只读属性的赋值:在严格模式下,对只读属性的赋值将导致错误。在正常模式下,这种操作通常不会引发错误。
    9.禁止删除不可删除的属性:在严格模式下,使用 delete 操作符删除不可删除的属性将导致错误。在正常模式下,这通常会返回 false,但不会引发错误。
    10.更强制的 eval() 行为:在严格模式下,eval() 中的代码无法在其包含的上下文之外创建变量。在正常模式下,它可以创建全局变量。

    严格模式 vs. 正常模式:区别和实例

    以下是一些示例,说明严格模式和正常模式之间的区别:

    变量声明和赋值:

    正常模式:

    x = 10; // 全局变量 x 被隐式创建
    
    • 1

    严格模式:

    "use strict";
    x = 10; // 抛出 ReferenceError:x 未定义
    
    • 1
    • 2

    在严格模式下,未声明的变量不能被赋值。

    this 绑定:

    正常模式:

    function doSomething() {
      console.log(this); // 全局对象
    }
    
    doSomething();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    严格模式:

    "use strict";
    function doSomething() {
      console.log(this); // undefined
    }
    
    doSomething();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在严格模式下,函数内部的 this 不会默认绑定到全局对象。

    删除变量:

    正常模式:

    var x = 10;
    delete x; // 返回 true,但 x 未定义
    
    • 1
    • 2

    严格模式:

    "use strict";
    var x = 10;
    delete x; // 抛出错误:无法删除
    
    • 1
    • 2
    • 3

    在严格模式下,使用 delete 删除变量将导致错误。

    重复的参数名:

    正常模式:

    function sum(x, x) {
      return x + x;
    }
    
    console.log(sum(1, 2)); // 4
    
    • 1
    • 2
    • 3
    • 4
    • 5

    严格模式:

    "use strict";
    function sum(x, x) {
      return x + x;
    }
    
    console.log(sum(1, 2)); // 抛出 SyntaxError:参数名重复
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在严格模式下,函数不允许有重复的参数名。

    八进制字面量:

    正常模式:

    var num = 0123; // 八进制字面量
    console.log(num); // 83
    
    • 1
    • 2

    严格模式:

    "use strict";
    var num = 0123; // 抛出 SyntaxError:八进制字面量无效
    
    • 1
    • 2

    在严格模式下,八进制字面量将导致错误。

    this 关键字的赋值:

    正常模式:

    function changeThis() {
      this = 42; // 有效
    }
    
    changeThis();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    严格模式:

    "use strict";
    function changeThis() {
      this = 42; // 抛出 TypeError:无法分配给“this”
    }
    
    changeThis();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在严格模式下,不允许对 this 关键字进行赋值。

    只读属性的赋值:

    正常模式:

    var obj = {};
    Object.defineProperty(obj, "x", { value: 42, writable: false });
    
    obj.x = 10; // 不会报错,但 x 的值不会改变
    
    • 1
    • 2
    • 3
    • 4

    严格模式:

    "use strict";
    var obj = {};
    Object.defineProperty(obj, "x", { value: 42, writable: false });
    
    obj.x = 10; // 抛出 TypeError:只读属性无法修改
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在严格模式下,对只读属性的赋值将导致错误。

    删除不可删除的属性:

    正常模式:

    var obj = {};
    Object.defineProperty(obj, "x", { value: 42, configurable: false });
    
    delete obj.x; // 返回 false,但属性未删除
    
    • 1
    • 2
    • 3
    • 4

    严格模式:

    "use strict";
    var obj = {};
    Object.defineProperty(obj, "x", { value: 42, configurable: false });
    
    delete obj.x; // 抛出 TypeError:无法删除属性
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在严格模式下,使用 delete 删除不可删除的属性将导致错误。

    保留字作为变量名:

    正常模式:

    var arguments = 42; // 有效
    console.log(arguments); // 42
    
    • 1
    • 2

    严格模式:

    "use strict";
    var arguments = 42; // 抛出 SyntaxError:无法将保留字用作变量名
    
    • 1
    • 2

    在严格模式下,一些保留字不能用作变量名。

    eval() 行为:

    正常模式:

    var x = 1;
    eval("var x = 2;");
    console.log(x); // 2,全局 x 被修改
    
    • 1
    • 2
    • 3

    严格模式:

    "use strict";
    var x = 1;
    eval("var x = 2;");
    console.log(x); // 1,全局 x 未被修改
    
    • 1
    • 2
    • 3
    • 4

    在严格模式下,eval() 中的代码无法在其包含的上下文之外创建变量。

    使用严格模式的好处

    使用严格模式有助于改善代码质量、降低错误风险并提高性能。以下是一些使用严格模式的好处:

    1.更安全的代码:严格模式可以帮助您捕获一些潜在的错误,例如意外的全局变量、不安全的 this 绑定和禁止 eval() 中的变量泄漏。
    2.更高效的 JavaScript:严格模式下,引擎可以进行更多的优化,从而提高代码的执行速度。
    3.更易维护的代码:严格模式要求更规范的代码编写,更少的潜在陷阱和更明确的行为,从而使代码更容易理解和维护。
    4.避免未来的冲突:ECMAScript 规范将来可能会引入新的保留字和语法。使用严格模式可以避免与未来版本的冲突。
    5.更好的错误报告:严格模式下,运行时错误更容易捕获,因为它会抛出更多的异常,而不是静默失败。
    6.减少全局污染:严格模式可以减少全局变量的污染,因为它要求显式声明变量。

    启用严格模式

    要在 JavaScript 中启用严格模式,您只需在脚本或函数的顶部添加特定的字符串:

    "use strict";
    
    • 1

    如果您将这个字符串添加到脚本的顶部,整个脚本都将在严格模式下执行。如果您只希望在特定函数内启用严格模式,可以将字符串添加到该函数的顶部。

    例如:

    "use strict";
    
    function myFunction() {
      // 这里是严格模式
    }
    
    function anotherFunction() {
      // 这里不是严格模式
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    严格模式的适用性和最佳实践

    尽管严格模式提供了许多好处,但并不是所有情况下都需要使用它。以下是一些使用严格模式的适用性和最佳实践:

    1. 新项目和新代码:对于新项目和新代码,建议启用严格模式,以避免常见的错误和提高代码质量。
      2.旧项目:在旧项目中,启用严格模式可能会导致一些现有代码不起作用。因此,在将严格模式引入现有项目之前,需要进行充分的测试和修复。
      3.特定函数:如果只需要在特定函数内使用严格模式,可以在该函数的顶部启用严格模式,而不必影响整个脚本。
      4.尊重第三方库:在使用第三方库或框架时,应尊重库的规则,不强制启用严格模式。如果库允许,您可以在自己的代码中启用严格模式。
      5.测试和部署:在使用严格模式的代码中,务必进行充分的测试,以确保它正常工作。在部署之前,确保您的代码在严格模式和正常模式下都能正确运行。

    总之,JavaScript 严格模式是一个有助于提高代码质量和性能的有用工具。通过了解其特点和使用最佳实践,您可以更好地应用它来编写更可靠和安全的 JavaScript 代码。然而,根据项目的需求和现有的代码基础,您应该权衡是否使用严格模式,以确保最佳的开发和维护体验。
    在这里插入图片描述

  • 相关阅读:
    新媒体时代如何做好新型的网络口碑营销?
    人工智能-卷积神经网络(LeNet)
    手把手教你定位线上MySQL锁超时问题,包教包会
    【Oracle】Oracle系列之十四--触发器
    对React fiber的理解
    【算法入门与九月打卡】—— 第五天
    每日两题 / 240. 搜索二维矩阵 II && 48. 旋转图像 - 力扣(LeetCode热题100)
    CSS 浮动布局
    万亿咖啡赛道或将再出一个IPO?窄门入局、宽门出圈的它,做对了什么?
    java基础10题
  • 原文地址:https://blog.csdn.net/wangxuanyang_zer/article/details/134020762