【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-附录B-严格模式
附录B、严格模式
-
严格模式
- ECMAScript 5 首次引入严格模式的概念。严格模式用于选择以更严格的条件检查 JavaScript 代码错误,可以应用到全局,也可以应用到函数内部。严格模式的好处是可以提早发现错误,因此可以捕获某些 ECMAScript 问题导致的编程错误。
- 理解严格模式的规则非常重要,因为未来的 ECMAScript 会逐步强制全局使用严格模式。严格模式已得到所有主流浏览器支持。
-
选择使用
- 要选择使用严格模式,需要使用严格模式编译指示(pragma),即一个不赋值给任何变量的字符串:
"use strict"; - 这样一个即使在 ECMAScript 3 中也有效的字符串,可以兼容不支持严格模式的 JavaScript 引擎。支持严格模式的引擎会启用严格模式,而不支持的引擎则会将这个编译指示当成一个未赋值的字符串字面量。
- 如果把这个编译指示应用到全局作用域,即函数外部,则整个脚本都会按照严格模式来解析。这意味着在最终会与其他脚本拼接为一个文件的脚本中添加了编译指示,会将该文件中的所有 JavaScript 置于严格模式之下。
- 也可以像下面这样只在一个函数内部开启严格模式:
function doSomething() { "use strict"; // 其他代码 } - 如果你不能控制页面中的所有脚本,那么建议只在经过测试的特定函数中启用严格模式。
- 要选择使用严格模式,需要使用严格模式编译指示(pragma),即一个不赋值给任何变量的字符串:
-
变量
- 严格模式下如何创建变量及何时会创建变量都会发生变化。第一个变化是不允许意外创建全局变量。在非严格模式下,以下代码可以创建全局变量:
// 变量未声明 // 非严格模式:创建全局变量 // 严格模式:抛出 ReferenceError message = "Hello world!"; - 虽然这里的 message 没有前置 let 关键字,也没有明确定义为全局对象的属性,但仍然会自动创建为全局变量。在严格模式下,给未声明的变量赋值会在执行代码时抛出 ReferenceError。
- 相关的另一个变化是无法在变量上调用 delete。在非严格模式下允许这样,但可能会静默失败(返回 false)。在严格模式下,尝试删除变量会导致错误:
// 删除变量 // 非严格模式:静默失败 // 严格模式:抛出 ReferenceError let color = "red"; delete color; - 严格模式也对变量名增加了限制。具体来说,不允许变量名为 implements、interface、let、package、private、protected、public、static 和 yield。这些是目前的保留字,可能在将来的 ECMAScript 版本中用到。如果在严格模式下使用这些名称作为变量名,则会导致语法错误。
- 严格模式下如何创建变量及何时会创建变量都会发生变化。第一个变化是不允许意外创建全局变量。在非严格模式下,以下代码可以创建全局变量:
-
对象
- 在严格模式下操作对象比在非严格模式下更容易抛出错误。严格模式倾向于在非严格模式下会静默失败的情况下抛出错误,增加了开发中提前发现错误的可能性。
- 首先,以下几种情况下试图操纵对象属性会引发错误。
- 给只读属性赋值会抛出 TypeError。
- 在不可配置属性上使用 delete 会抛出 TypeError。
- 给不存在的对象添加属性会抛出 TypeError。
- 另外,与对象相关的限制也涉及通过对象字面量声明它们。在使用对象字面量时,属性名必须唯一。例如:
// 两个属性重名 // 非严格模式:没有错误,第二个属性生效 // 严格模式:抛出 SyntaxError let person = { name: "Nicholas", name: "Greg" }; - 这里的对象字面量 person 有两个叫作 name 的属性。第二个属性在非严格模式下是最终的属性。但在严格模式下,这样写是语法错误。
- 注意,ECMAScript 6 删除了对重名属性的这个限制,即在严格模式下重复的对象字面量属性键不会抛出错误。
-
函数
- 首先,严格模式要求命名函数参数必须唯一。看下面的例子:
// 命名参数重名 // 非严格模式:没有错误,只有第二个参数有效 // 严格模式:抛出 SyntaxError function sum (num, num){ // 函数代码 } - 在非严格模式下,这个函数声明不会抛出错误。这样可以通过名称访问第二个 num,但只能通过arguments 访问第一个参数。
- arguments 对象在严格模式下也有一些变化。在非严格模式下,修改命名参数也会修改 arguments对象中的值。而在严格模式下,命名参数和 arguments 是相互独立的。例如:
// 修改命名参数的值 // 非严格模式:arguments 会反映变化 // 严格模式:arguments 不会反映变化 function showValue(value){ value = "Foo"; alert(value); // "Foo" alert(arguments[0]); // 非严格模式:"Foo" // 严格模式:"Hi" } showValue("Hi"); - 在这个例子中,函数 showValue()有一个命名参数 value。调用这个函数时给它传入参数"Hi",该值会赋给value。在函数内部,value被修改为"Foo"。在非严格模式下,这样也会修改arguments[0]的值,但在严格模式下则不会。
- 另一个变化是去掉了 arguments.callee 和 arguments.caller。在非严格模式下,它们分别引用函数本身和调用函数。在严格模式下,访问这两个属性中的任何一个都会抛出 TypeError。例如:
// 访问 arguments.callee // 非严格模式:没问题 // 严格模式:抛出 TypeError function factorial(num){ if (num <= 1) { return 1; } else { return num * arguments.callee(num-1) } } let result = factorial(5); - 类似地,读或写函数的 caller 或 callee 属性也会抛出 TypeError。因此对这个例子而言,访问factorial.caller 和 factorial.callee 也会抛出错误。
- 另外,与变量一样,严格模式也限制了函数的命名,不允许函数名为 implements、interface、let、package、private、protected、public、static 和 yield。
- 关于函数的最后一个变化是不允许函数声明,除非它们位于脚本或函数的顶级。这意味着在 if 语句中声明的函数现在是个语法错误:
// 在 if 语句中声明函数 // 非严格模式:函数提升至 if 语句外部 // 严格模式:抛出 SyntaxError if (true){ function doSomething(){ // ... } }
- 首先,严格模式要求命名函数参数必须唯一。看下面的例子:
-
函数参数
- ES6 增加了剩余操作符、解构操作符和默认参数,为函数组织、结构和定义参数提供了强大的支持。ECMAScript 7 增加了一条限制,要求使用任何上述先进参数特性的函数内部都不能使用严格模式,否则会抛出错误。不过,全局严格模式还是允许的。
// 可以 function foo(a, b, c) { "use strict"; } // 不可以 function bar(a, b, c='d') { "use strict"; } // 不可以 function baz({a, b, c}) { "use strict"; } // 不可以 function qux(a, b, ...c) { "use strict"; } - ES6 增加的这些新特性期待参数与函数体在相同模式下进行解析。如果允许编译指示"use strict"出现在函数体内,JavaScript 解析器就需要在解析函数参数之前先检查函数体内是否存在这个编译指示,而这会带来很多问题。为此,ES7 规范增加了这个约定,目的是让解析器在解析函数之前就确切知道该使用什么模式。
- ES6 增加了剩余操作符、解构操作符和默认参数,为函数组织、结构和定义参数提供了强大的支持。ECMAScript 7 增加了一条限制,要求使用任何上述先进参数特性的函数内部都不能使用严格模式,否则会抛出错误。不过,全局严格模式还是允许的。
-
eval()
- eval()函数在严格模式下也有变化。最大的变化是 eval()不会再在包含上下文中创建变量或函数。例如:
// 使用 eval()创建变量 // 非严格模式:警告框显示 10 // 严格模式:调用 alert(x)时抛出 ReferenceError function doSomething(){ eval("let x = 10"); alert(x); } - 以上代码在非严格模式下运行时,会在 doSomething()函数内部创建局部变量 x,然后 alert()会显示这个变量的值。在严格模式下,调用 eval()不会在 doSomething()中创建变量 x,由于 x 没有声明,alert()会抛出 ReferenceError。
- 变量和函数可以在 eval()中声明,但它们会位于代码执行期间的一个特殊的作用域里,代码执行完毕就会销毁。因此,以下代码就不会出错:
"use strict"; let result = eval("let x = 10, y = 11; x + y"); alert(result); // 21 - 这里在 eval()中声明了变量 x 和 y,将它们相加后返回得到的结果。变量 result 会包含 x 和 y相加的结果 21,虽然 x 和 y 在调用 alert()时已经不存在了,但不影响结果的显示。
- eval()函数在严格模式下也有变化。最大的变化是 eval()不会再在包含上下文中创建变量或函数。例如:
-
eval 与 arguments
- 严格模式明确不允许使用 eval 和 arguments 作为标识符和操作它们的值。例如:
// 将 eval 和 arguments 重新定义为变量 // 非严格模式:可以,没有错误 // 严格模式:抛出 SyntaxError let eval = 10; let arguments = "Hello world!"; - 在非严格模式下,可以重写 eval 和 arguments。在严格模式下,这样会导致语法错误。不能用它们作为标识符,这意味着下面这些情况都会抛出语法错误:
- 使用 let 声明;
- 赋予其他值;
- 修改其包含的值,如使用++;
- 用作函数名;
- 用作函数参数名;
- 在 try/catch 语句中用作异常名称。
- 严格模式明确不允许使用 eval 和 arguments 作为标识符和操作它们的值。例如:
-
this 强制转型
- JavaScript 中最大的一个安全问题,也是最令人困惑的一个问题,就是在某些情况下 this 的值是如何确定的。使用函数的 apply()或 call()方法时,在非严格模式下 null 或 undefined 值会被强制转型为全局对象。在严格模式下,则始终以指定值作为函数 this 的值,无论指定的是什么值。例如:
// 访问属性 // 非严格模式:访问全局属性 // 严格模式:抛出错误,因为 this 值为 null let color = "red"; function displayColor() { alert(this.color); } displayColor.call(null); - 这里在调用 displayColor.call()时传入 null 作为 this 的值,在非严格模式下该函数的 this值是全局对象。结果会显示"red"。在严格模式下,该函数的 this 值是 null,因此在访问 null 的属性时会抛出错误。
- 通常,函数会将其 this 的值转型为一种对象类型,这种行为经常被称为“装箱”(boxing)。这意味着原始值会转型为它们的包装对象类型。
function foo() { console.log(this); } foo.call(); // Window {} foo.call(2); // Number {2} - 在严格模式下执行以上代码时,this 的值不会再“装箱”:
function foo() { "use strict"; console.log(this); } foo.call(); // undefined foo.call(2); // 2
- JavaScript 中最大的一个安全问题,也是最令人困惑的一个问题,就是在某些情况下 this 的值是如何确定的。使用函数的 apply()或 call()方法时,在非严格模式下 null 或 undefined 值会被强制转型为全局对象。在严格模式下,则始终以指定值作为函数 this 的值,无论指定的是什么值。例如:
-
类与模块
- 类和模块都是 ECMAScript 6 新增的代码容器特性。在之前的 ECMAScript 版本中没有类和模块这两个概念,因此不用考虑从语法上兼容之前的 ECMAScript 版本。为此,TC39 委员会决定在 ES6 类和模块中定义的所有代码默认都处于严格模式。
- 对于类,这包括类声明和类表达式,构造函数、实例方法、静态方法、获取方法和设置方法都在严格模式下。对于模块,所有在其内部定义的代码都处于严格模式。
-
其他变化
- 严格模式下还有其他一些需要注意的变化。首先是消除 with 语句。with 语句改变了标识符解析时的方式,严格模式下为简单起见已去掉了这个语法。在严格模式下使用 with 会导致语法错误:
// 使用 with 语句 // 非严格模式:允许 // 严格模式:抛出 SyntaxError with(location) { alert(href); } - 严格模式也从 JavaScript 中去掉了八进制字面量。八进制字面量以前导 0 开始,一直以来是很多错误的源头。在严格模式下使用八进制字面量被认为是无效语法:
// 使用八进制字面量 // 非严格模式:值为 8 // 严格模式:抛出 SyntaxError let value = 010; - ECMAScript 5修改了非严格模式下的parseInt(),将八进制字面量当作带前导0的十进制字面量。例如:
// 在 parseInt()中使用八进制字面量 // 非严格模式:值为 8 // 严格模式:值为 10 let value = parseInt("010");
- 严格模式下还有其他一些需要注意的变化。首先是消除 with 语句。with 语句改变了标识符解析时的方式,严格模式下为简单起见已去掉了这个语法。在严格模式下使用 with 会导致语法错误:
相关文章:
【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-附录B-严格模式
附录B、严格模式 严格模式 ECMAScript 5 首次引入严格模式的概念。严格模式用于选择以更严格的条件检查 JavaScript 代码错误,可以应用到全局,也可以应用到函数内部。严格模式的好处是可以提早发现错误,因此可以捕获某些 ECMAScript 问题导致…...
跨平台 C++ 程序崩溃调试与 Dump 文件分析
前言 C 程序在运行时可能会由于 空指针访问、数组越界、非法内存访问、栈溢出 等原因崩溃。为了分析崩溃原因,我们通常会生成 Dump 文件(Windows 的 .dmp,Linux 的 core,macOS 的 .crash),然后用调试工具分…...
缺陷VS质量:为何软件缺陷是质量属性的致命对立面?
为何说缺陷是质量的对立面? 核心逻辑:软件质量的定义是“满足用户需求的程度”,而缺陷会直接破坏这种满足关系。 对立性:缺陷的存在意味着软件偏离了预期行为(如功能错误、性能不足、安全性漏洞等)&#…...
伍[5],伺服电机,电流环,速度环,位置环
电流环、速度环和位置环是电机控制系统中常见的三个闭环控制环节,通常采用嵌套结构(内环→外环:电流环→速度环→位置环),各自负责不同层级的控制目标。以下是它们的详细说明及相互关系: 1. 电流环(最内环) 作用:控制电机的电流,间接控制输出转矩(τ=Kt⋅Iτ=Kt⋅…...
RuntimeError: CUDA error: device-side assert triggered
RuntimeError: CUDA error: device-side assert triggered 欢迎来到英杰社区,这里是博主英杰https://bbs.csdn.net/topics/617804998 原因: cuda运行可能是异步的(asynchronously),因此报错信息中提示的位置可能不准确…...
清华大学Deepseek第六版AIGC发展研究3.0(共186页,附PDF下载)
人工智能生成内容(AIGC)正以前所未有的速度改变我们的生活。 2024年底,清华大学新闻与传播学院与人工智能学院联合发布了《AIGC发展研究3.0版》,这份报告系统梳理了AIGC技术的突破性进展、应用场景及社会影响,并展望了…...
SpringBoot生成唯一ID的方式
1.为什么要生成唯一ID? 数据唯一性:每个记录都需要有一个独一无二的标识符来确保数据的唯一性。这可以避免重复的数据行,并有助于准确地查询、更新或删除特定的记录。 数据完整性:通过使用唯一ID,可以保证数据库中的数…...
通俗易懂的分类算法之K近邻详解
通俗易懂的分类算法之K近邻详解 用最通俗的语言和例子,来彻底理解 K近邻(K-Nearest Neighbors,简称 KNN) 这个分类算法。不用担心复杂的数学公式,我会用生活中的例子来解释,保证你一听就懂! 1.…...
CSDN markdown 操作指令等
CSDN markdown 操作指令等 页内跳转 [内容](#1) <div id"1"> </div>...
【linux】文件与目录命令 - uniq
文章目录 1. 基本用法2. 常用参数3. 用法举例4. 注意事项 uniq 命令用于过滤文本文件中相邻的重复行,并支持统计重复次数或仅保留唯一行。它通常与 sort 命令配合使用,因为 uniq 只识别相邻的重复行。 1. 基本用法 语法: uniq [选项] [输入…...
零信任沙箱:为网络安全筑牢“隔离墙”
在数字化浪潮汹涌澎湃的今天,网络安全如同一艘船在波涛汹涌的大海中航行,面临着重重挑战。数据泄露、恶意软件攻击、网络钓鱼等安全威胁层出不穷,让企业和个人用户防不胜防。而零信任沙箱,就像是一座坚固的“隔离墙”,…...
【金融量化】Ptrade中交易环境支持的业务类型
1. 普通股票买卖 • 特点: 普通股票买卖是最基础的交易形式,投资者通过买入和卖出上市公司的股票来获取收益。 ◦ 流动性高:股票市场交易活跃,买卖方便。 ◦ 收益来源多样:包括股价上涨的资本利得和公司分红。 ◦ 风险…...
【Java---数据结构】链表 LinkedList
1. 链表的概念 链表用于存储一系列元素,由一系列节点组成,每个节点包含两部分:数据域和指针域。 数据域:用于存储数据元素 指针域:用于指向下一个节点的地址,通过指针将各个节点连接在一起,形…...
紧跟 Web3 热潮,RuleOS 如何成为行业新宠?
Web3 热潮正以汹涌之势席卷全球。从金融领域的创新应用到供应链管理的变革,从社交媒体的去中心化尝试到游戏产业的全新玩法探索,Web3 凭借其去中心化、安全性和用户赋权等特性,为各个行业带来了前所未有的机遇。在这股热潮中,Rule…...
CC++的内存管理
目录 1、C/C内存划分 C语言的动态内存管理 malloc calloc realloc free C的动态内存管理 new和delete operator new函数和operator delete函数 new和delete的原理 new T[N]原理 delete[]的原理 1、C/C内存划分 1、栈:存有非静态局部变量、函数参数、返回…...
Spark核心之02:RDD、算子分类、常用算子
spark内存计算框架 一、目标 深入理解RDD弹性分布式数据集底层原理掌握RDD弹性分布式数据集的常用算子操作 二、要点 ⭐️1. RDD是什么 RDD(Resilient Distributed Dataset)叫做**弹性分布式数据集,是Spark中最基本的数据抽象,…...
【Resis实战分析】Redis问题导致页面timeout知识点分析
事故现象:前端页面返回timeout 事故回溯总结一句话: (1)因为大KEY调用量,随着白天自然流量趋势增长而增长,最终在业务高峰最高点期占满带宽使用100%。   (2&#x…...
单一职责原则(设计模式)
目录 问题: 定义: 解决: 方式 1:使用策略模式 示例:用户管理 方式 2:使用装饰者模式 示例:用户操作 方式 3:使用责任链模式 示例:用户操作链 总结 推荐 问题&a…...
生理信号概念
rPPG 信号(远程光电容积脉搏波信号) 原理: 基于光电容积脉搏波描记法,利用普通摄像头,在一定距离外捕捉人体皮肤表面因心脏泵血导致的血液容积变化引起的细微颜色变化,通过图像处理和信号分析算法提取心率…...
安卓内存泄露之DMA-BUF异常增长:Android Studio镜像引起DMA内存泄露
安卓内存泄露之DMA-BUF异常增长:Android Studio镜像引起DMA内存泄露 - Wesley’s Blog 今天用着安卓 14 的板子的时候突然系统卡死。 查看日志发现launcher都被干掉了 03-04 06:13:35.544 7872 8479 I ActivityManager: vis BFGS 18740: com.android.launcher3 (pid 8407) se…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...
解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
Docker、Wsl 打包迁移环境
电脑需要开启wsl2 可以使用wsl -v 查看当前的版本 wsl -v WSL 版本: 2.2.4.0 内核版本: 5.15.153.1-2 WSLg 版本: 1.0.61 MSRDC 版本: 1.2.5326 Direct3D 版本: 1.611.1-81528511 DXCore 版本: 10.0.2609…...
el-amap-bezier-curve运用及线弧度设置
文章目录 简介示例线弧度属性主要弧度相关属性其他相关样式属性完整示例链接简介 el-amap-bezier-curve 是 Vue-Amap 组件库中的一个组件,用于在 高德地图 上绘制贝塞尔曲线。 基本用法属性path定义曲线的路径,可以是多个弧线段的组合。stroke-weight线条的宽度。stroke…...
SFTrack:面向警务无人机的自适应多目标跟踪算法——突破小尺度高速运动目标的追踪瓶颈
【导读】 本文针对无人机(UAV)视频中目标尺寸小、运动快导致的多目标跟踪难题,提出一种更简单高效的方法。核心创新在于从低置信度检测启动跟踪(贴合无人机场景特性),并改进传统外观匹配算法以关联此类检测…...
