第1行字符1处的问题:缺少“use strict”语句。
-
74 这里的答案很古老,但它们是错误的。 strict模式的主要原因不是为了防止编程错误,而是为了使JavaScript具有词汇范围,以便可以进行静态分析:] – 本杰明·格伦鲍姆 评论 2019年9月6日11:40 -
5 奇怪语法(作为语句的魔法字符串)的原因是为了使其向后兼容旧的JavaScript引擎。 严格模式的思想是不允许一些有问题的JavaScript语言构造,但不更改代码的解释,这样无论JavaScript引擎是否真正支持严格模式,执行都是相同的。 – 米科·兰塔莱宁 评论 2022年9月30日7:11 -
2 @Benjamin Gruenbaum,但使其可静态分析的原因是,可以通过工具对其进行分析,以防止编程错误 – 橙色小狗 评论 4月22日8:37 -
@OrangeDog不,它是静态分析谷歌的广告代码以防止注入和沙盒escpe-参见 static.googleusercontent.com/media/research.google.com/en//pubs/… – 本杰明·格伦鲍姆 评论 4月24日17:53 -
2 @Benjamin Gruenbaum这些是编程错误 – 橙色小狗 评论 4月24日23:01
32个答案
ES6模块更新
原始答案
严格模式是ECMAScript 5中的一个新功能,它允许您将程序或函数放置在“严格”的操作上下文中。 这种严格的上下文阻止执行某些操作,并引发更多异常。
严格模式有两种帮助:
它捕获一些常见的编码错误,引发异常。 当采取相对“不安全”的操作(例如访问全局对象)时,它可以防止或引发错误。 它禁用了令人困惑或考虑不周的功能。
//非严格代码。。。 (函数(){ “使用严格”; //严格定义库。。。 })(); //非标准代码。。。
功能列表(非详尽)
不允许全局变量。 (抓钩缺失 无功功率,无功功率 变量名中的声明和输入错误) 无声失败的分配将在严格模式下引发错误(分配 NaN=5; ) 尝试删除不可删除的属性将引发( 删除对象.原型 ) 要求对象文本中的所有属性名称都是唯一的( varx={x1:“1”,x1:“2”} ) 函数参数名称必须唯一( 函数和(x,x){…} ) 禁止八进制语法( var x=023; 一些开发人员错误地认为前面的零不会改变数字。) 禁止 具有 关键字 评估 在strict模式下不引入新变量 禁止删除普通名称( 删除x; ) 禁止绑定或分配名称 评估 和 论据 以任何形式 严格模式不别名 论据 具有形式参数的对象。 (例如in 函数sum(a,b){返回参数[0]+b;} 这起作用是因为 参数[0] 已绑定到 一 等等。)( 请参见 示例 了解差异 ) 参数.被叫 不支持
严格模式代码不别名在其中创建的参数对象的属性
功能显示(消息){ 消息=42; 控制台.log(消息);// 消息===42 console.log(参数[0]);// 参数===42 } 秀(“嘿”); //在严格模式下,参数[i]不跟踪的值 //相应的命名参数,命名参数也不跟踪相应参数[i]中的值 函数showStrict(消息){ “使用严格”; 消息=42; 控制台.log(消息);// 消息===42 console.log(参数[0]);// arguments===“嘿” } showStrict(“嘿”);
函数isStrictMode(){ 返回! 这; } /* 返回false,因为“this”指的是全局对象 '! 这个'变为假 */ 函数isStrictMode(){ “使用严格”; 返回! 这; } /* 返回true,因为在严格模式下关键字“this” 与传统JS不同,它不引用全局对象。 所以这里,“this”是“undefined”和“!”! 这变成了事实。 */
使用 '使用严格';
不会突然让代码变得更好。
'使用严格';
变量a=365; 变量b=030;
我应该在哪里使用 “严格使用”;
?
在我的 新的 JavaScript应用程序: 当然! 当您在代码中做一些愚蠢的事情时,可以使用严格模式作为告密者。 在我的 现有的 JavaScript代码: 可能不会! 如果您现有的JavaScript代码包含严格模式中禁止的语句,那么应用程序将完全中断。 如果您想要严格模式,您应该准备调试和更正现有代码。 这就是为什么 使用 '使用严格'; 不会突然让代码变得更好 .
如何使用严格模式?
插入一个 '使用严格'; 脚本顶部的语句: //文件:myscript.js “严格使用”; 变量a=2; .... 请注意,文件中的所有内容 myscript.js(myscript.js) 将以严格模式解释。 或者,插入 '使用严格'; 函数体顶部的语句: 函数doSomething(){ '使用严格'; ... } 中的所有内容 词汇范围 函数的 做点什么 将以严格模式解释。 这个词 词汇范围 在这里很重要。 例如,如果您的 严格的 代码调用库的函数 不严格 ,只有您的代码在严格模式下执行,而不是被调用的函数。 请参见 这个答案 以获得更好的解释。
严格禁止哪些事情?
范围
从历史上看,JavaScript一直被混淆于其功能 确定了范围。 有时它们似乎是静态范围的,但有些 这些特性使它们的行为类似于动态范围。 这是 令人困惑,使程序难以阅读和理解。 误解会导致错误。 这也是一个性能问题。 静态范围将允许在编译时进行变量绑定 时间,但对动态范围的要求意味着绑定必须 推迟到运行时,这会带来显著的性能 处罚。
严格模式要求所有变量绑定都是静态的。 这意味着以前需要动态绑定的功能 必须删除或修改。 具体来说,with语句是 以及eval函数篡改 呼叫方的环境受到严格限制。
严格代码的好处之一是 YUI压缩机 在处理时可以做得更好。
隐含的全局变量
JavaScript具有隐含的全局变量。 如果 您没有显式声明变量,全局变量是 为您隐式声明。 这使得编程更容易 初学者,因为他们可以忽略一些基本的家务 家务活。 但它使大型项目的管理变得更加重要 这很困难,并且会显著降低可靠性。 所以严格来说 模式下,不再创建隐含的全局变量。 你应该 显式声明所有变量。
全球泄漏
有许多情况可能导致
这 以绑定到全局对象。 例如,如果你忘记了 提供
新的 调用构造函数时使用前缀 建造师的
这 将意外绑定到全局对象,因此 它将以静默方式代替初始化新对象 篡改全局变量。 在这些情况下,严格模式将 而是绑定
这 到
未定义 ,这将导致构造函数 相反,抛出一个异常,使错误能够被检测到 更快。
噪音故障
JavaScript始终具有只读属性,但您 在ES5之前无法自己创建
对象.创建属性 功能公开了该功能。 如果您试图赋值 对于只读属性,它将以静默方式失败。 这项任务将 不会更改属性的值,但您的程序将按 尽管有。 这是一个完整性风险,可能导致程序 进入不一致的状态。 在严格模式下,尝试更改 只读属性将引发异常。
八角形
数字的八进制(或以8为基数)表示法极其复杂 在使用word的机器上进行机器级编程时很有用 大小是3的倍数。 你在CDC工作时需要八进制 6600大型机,其字长为60位。 如果你能阅读 八进制,你可以把一个单词看作20个数字。 表示两位数 操作码和一个数字标识了8个寄存器中的一个。 在 从机器代码到高级语言的缓慢过渡 被认为有助于在编程语言中提供八进制形式。
在C中,八度的一个极其不幸的表示是 selected:前导零。 所以在C中,
0100 是指64,而不是100,以及
08 是一个 错误,而不是8。 更不幸的是,这种不合时宜的做法 复制到几乎所有现代语言中,包括JavaScript,其中 它只用于创建错误。 它没有其他用途。 所以在 严格模式下,不再允许使用八进制形式。
等等
参数伪数组变得有点多 ES5中的阵列。 在严格模式下,它会丢失
被叫方 和
呼叫者 属性。 这样可以通过
论据 到不受信任 在不放弃大量机密上下文的情况下编写代码。 此外
论据 函数的性质被消除了。
在严格模式下,函数文本中的重复键将生成 语法错误。 函数不能有两个同名参数。 函数不能有与其同名的变量 参数。 函数不能
删除 它自己的变量。 试图
删除 非可配置属性现在引发异常。 基本体 值没有隐式包装。
未来JavaScript版本的保留字
实施 ,
接口 ,
让 ,
包裹 ,
私有的 ,
受保护的 ,
公众的 ,
静止的 、和
产量
进一步阅读
var人={ 名称:'xyz', 位置:'abc', 全名:function(){“use strict”;return this.name;} };
使用严格 不包含关键字:该指令是一个简单的表达式语句,由一个特殊的字符串文字(单引号或双引号)组成。 不实现ECMAScript 5的JavaScript引擎只看到一个没有副作用的表达式语句。 预计ECMAScript标准的未来版本将引入 使用 作为一个真正的关键词; 因此,这些引文将过时。 使用严格 只能在脚本或函数的开头使用,即它必须位于每个其他(实数)语句之前。 它不一定是函数脚本中的第一条指令:它前面可以是由字符串文字组成的其他语句表达式(JavaScript实现可以将它们视为特定于实现的指令)。 字符串文字语句是简单的表达式语句,紧跟在第一个实数语句之后(在脚本或函数中)。 口译员不得将其解释为指令,且无效。
您不能使用 具有 -严格模式下的语句。 在严格模式下,必须声明所有变量:如果将值赋给尚未声明为变量、函数、函数参数、catch-clause参数或全局属性的标识符 对象 ,然后您将获得 引用错误 在正常模式下,标识符隐式声明为全局变量(作为全局变量的属性 对象 ) 在严格模式下,关键字 这 具有价值 未定义 在作为函数(而不是作为方法)调用的函数中。 (在正常模式下 这 总是指向全局 对象 ). 此差异可用于测试实现是否支持严格模式:
var hasStrictMode=(function(){“use strict”;返回this===未定义}());
也可以使用调用函数 调用() 或 应用 在严格模式下,那么 这 的第一个参数的值 调用() 或 应用() 调用。 (在正常模式下 无效的 和 未定义 被全局替换 对象 和非对象的值被转换为对象。) 在严格模式下,您将获得 类型错误 ,当您尝试为只读属性赋值或为不可扩展对象定义新属性时。 (在正常模式下,两者都会失败,但没有错误消息。) 在严格模式下,将代码传递给 评估() ,不能在调用程序的作用域中声明或定义变量或函数(在正常模式下可以这样做)。 相反,将为创建一个新范围 评估() 变量和函数都在这个范围内。 该范围在 评估() 完成执行。 在严格模式下,函数的arguments-object包含传递给该函数的值的静态副本。 在正常模式下,arguments-object有一种“神奇”的行为:数组元素和命名函数参数引用相同的值。 在严格模式下,您将获得 语法错误 当 删除 运算符后面是非限定标识符(变量、函数或函数参数)。 在正常模式下 删除 表达式将不执行任何操作,并被计算为 假 . 在严格模式下,您将获得 类型错误 尝试删除不可配置属性时。 (在正常模式下,尝试失败 删除 表达式的计算结果为 假 ). 在严格模式下,当您试图为一个对象文字定义几个具有相同名称的属性时,这被认为是一个语法错误。 (在正常模式下没有错误。) 在严格模式下,当函数声明具有多个同名参数时,将被视为语法错误。 (在正常模式下没有错误。) 在严格模式下,不允许使用八进制文字(这些是以开头的文字 0 。(在正常模式下,某些实现确实允许使用八进制文字。) 在严格模式下,标识符 评估 和 论据 被视为关键字。 您不能更改它们的值,不能为它们赋值,也不能将它们用作catch块的变量、函数、函数参数或标识符的名称。 在严格模式下,对检查调用堆栈的可能性有更多限制。 论点.caller 和 参数.被叫 导致 类型错误 在严格模式下的函数中。 此外,严格模式下函数的一些调用方和参数属性会导致 类型错误 当你试图阅读它们时。
“使用严格”; var tree1Data={name:'香蕉树',年龄:100,叶计数:100000}; 功能树(typeOfTree){ var年龄; var叶计数; age=类型OfTree.age; leafCount=类型OfTree.leafCount; nameoftree=类型OfTree.name; }; var tree1=新树(tree1Data); console.log(窗口);
未捕获引用错误:未定义树名
“严格使用”; var树1数据={ name:'香蕉树', 年龄:100, 叶数:100000 }; 功能树(typeOfTree){ var年龄; var叶计数; age=类型OfTree.age; leafCount=类型OfTree.leafCount; //nameoftree=typeOfTree.name; 对于(var i=0;i<2;++i){ //让(leafCount=i){/*做某事*/} } 对于(var i=0;i<2;++i){ 使用(leafCount=i){/*做某事*/} } }; var tree1=新树(tree1Data); console.log(窗口);
Uncaught SyntaxError:对象文本中存在重复的数据属性 在严格模式下允许
“使用严格”; var树1数据={ name:'香蕉树', 年龄:100, 叶数:100000, name:‘香蕉树’ };
为将来的ECMAScript版本铺平道路 ,使用新保留的关键字之一(在预览中 ECMA脚本6 ): 实施 , 接口 , 让 , 包裹 , 私有的 , 受保护的 , 公众的 , 静止的 、和 产量 . 以块为单位声明函数 如果(a<b){函数f(){}} 八进制语法 变量n=023; 这 指向全局对象。 函数f(){ “使用严格”; 这.a=1; }; f(); 在对象文本中为属性名称声明两次相同的名称 {a:1,b:3,a:7} ECMAScript 6不再是这种情况( 错误1041128 ). 使用相同名称的函数声明两个函数参数 f(a,b,b){} 将值设置为未声明的变量 函数f(x){ “使用严格”; 变量a=12; b=a+x*35;// 错误! } f(); 使用 删除 关于变量名 删除myVariable; 使用 评估 或 论据 作为变量或函数参数名 “严格使用”; 参数++; var obj={设置p(参数){}}; 尝试{}catch(参数){} 函数参数(){}
转换为严格模式 在MDN上 严格模式 在MDN上 JavaScript的严格模式及其使用原因 Colin J.Ihrig的博客(存档版本)
通过更改来消除一些JavaScript静默错误 抛出错误。 修复了使JavaScript难以使用的错误 引擎执行优化。 禁止将来可能定义的某些语法 ECMAScript的版本。
“严格使用”指令
JavaScript 1.8.5(ECMAScript)中新增了“use-strict”指令 版本5)。
它不是一个语句,而是一个文字表达式,被前面的 JavaScript版本。
“使用严格”的目的是表明代码应该 以“严格模式”执行。
例如,在严格模式下,您不能使用未声明的变量。
为什么选择严格模式?
严格模式使编写“安全”JavaScript更容易。
严格模式将以前接受的“错误语法”更改为实际错误。
例如,在普通JavaScript中,错误键入变量名会创建 一个新的全局变量。 在严格模式下,这将引发错误, 不可能意外创建全局变量。
在普通JavaScript中,开发人员不会收到任何错误反馈 为不可写属性赋值。
在严格模式下,对不可写属性的任何赋值 getter-only属性、不存在的属性、不存的属性 变量或不存在的对象将引发错误。
“严格使用”指令 “use strict”指令在中是新的 JavaScript 1.8.5(ECMAScript版本5)。 这不是一个声明,而是一个 文字表达式,被早期版本的JavaScript忽略。 这个 “使用严格”的目的是表明代码应该 以“严格模式”执行。 例如,在严格模式下,您不能, 使用未声明的变量。
使用“use strict”的示例: 函数的严格模式:同样,要为 函数,放置精确语句“使用严格”; 中的(或“use strict”;) 函数体位于任何其他语句之前。
函数strict(){ //功能级严格模式语法 '使用严格'; function nested(){return“我也是!”;} return“嗨!我是一个严格模式函数!”+nested(); } 函数notStrict(){return“我不严格。”;} console.log(strict(),notStrict());
'使用严格'; var v=“嗨!我是一个严格模式脚本!”; console.log(v);
'使用严格'; //分配给不可写全局 var未定义=5;// 引发TypeError var无限=5;// 引发TypeError //不可写属性的赋值 变量obj1={}; Object.defineProperty(obj1,'x',{value:42,writable:false}); obj1.x=9;// 引发TypeError //对getter-only属性的赋值 var obj2={getx(){return 17;}}; 对象2.x=5;// 引发TypeError //分配给不可扩展对象上的新属性。 var固定={}; Object.proventExtensions(固定); fixed.newProp='ohai';// 引发TypeError
for(i of[1,2,3])console.log(i) //输出: // 1 // 2 // 3
'使用严格'; for(i of[1,2,3])console.log(i) //输出: //未捕获引用错误:未定义i
String.prototype.test=函数(){ console.log(此类型===“字符串”); }; “a”.test(); //输出 //假
String.prototype.test=函数(){ '使用严格'; console.log(类型为==='string'); }; “a”.test(); //输出 //真的
如果全局代码以包含使用严格指令的指令序言开头,则它是严格模式代码(参见14.1.1)。 模块代码始终是严格的模式代码。 a的所有部分 类别声明 或a 类表达式 是严格的模式代码。 如果评估代码以包含使用严格指令的指令序言开头,或者如果对评估的调用是包含在严格模式代码中的直接评估(参见12.3.4.1),则评估代码是严格模式代码。 如果关联 函数声明、函数表达式、生成器声明、生成器表达式、MethodDefinition或ArrowFunction 包含在严格模式代码中,或者如果生成函数[[ECMAScriptCode]]内部槽值的代码以包含Use strict Directive的Directive Prologue开头。 如果最后一个参数是String,而处理时该字符串是 功能体 以包含使用严格指令的指令序言开始。
防止意外声明全局变量。 使用 “使用strict()” 将确保使用声明变量 无功功率,无功功率 使用前。 如: 函数useStrictDemo(){ '使用严格'; //工作正常 var a='没有问题'; //工作不正常并抛出错误 k=“问题” //即使这样也会抛出错误 someObject={“问题”:“很多问题”}; } 注意: “使用严格” 指令只能在脚本或函数的开头识别。 字符串 “参数” 不能用作变量: “严格使用”; var参数=3.14;// 这将导致错误 将限制将关键字用作变量。 尝试使用它们会抛出错误。
(函数(){ “使用严格”; 你的代码。。。 })();
如果尝试赋值给未声明的变量,则显示错误 阻止您覆盖关键JS系统库 禁止一些不安全或容易出错的语言功能
ECMAScript版本5中新增了“use-strict”指令。 它不是一个语句,而是一个文字表达式,被前面的 JavaScript版本。 “使用严格”的目的是表明代码应该 以“严格模式”执行。 例如,在严格模式下,您不能使用未声明的变量。
设o={ name:'无名氏', sayName:函数(){ console.log(this.name); } }; o.sayName();//' 约翰·多伊
函数run(){ console.log(this); } run();// 窗口
“使用严格” 函数run(){ console.log(this); } run();// 未定义
函数getname(){ name=“堆栈溢出”;// 不使用var关键字 返回名称; } 获取名称(); console.log(名称);// 堆栈溢出
“使用严格” 函数getname(){ name=“堆栈溢出”;// 不使用var关键字 返回名称; } 获取名称(); console.log(名称);
未捕获引用错误:未定义名称 在getname(<匿名>:3:15) <匿名>:6:5
它是否被视为最佳实践之一?
这对用户代理意味着什么?
var city=“芝加哥” console.log(city)//打印城市名称,即芝加哥
city=“芝加哥” console.log(city)//打印城市名称,即芝加哥
那么,为什么在这两种情况下都要打印变量名呢?
'使用严格'; city=“芝加哥” console.log(city)//引用错误:asignment是未声明的变量city。
模块导出={ 环境:{ es6:正确 }, 规则:{ strict:['error','global'], }, };
好吧,那么在严格模式下可以防止什么呢?
使用变量而不声明它 将在严格模式下抛出错误。 这是为了防止在整个应用程序中无意中创建全局变量。 打印Chicago的示例特别涵盖了这一点。 删除变量、函数或参数 在严格模式下为no-no。 “使用严格”; 函数x(p1,p2){}; 删除x;// 这将导致错误 复制参数名称 是 不 在严格模式下允许。 “使用严格”; 函数x(p1,p1){};// 这将导致错误 不允许使用Javascript语言中的保留字 在严格模式下。 单词是implements interface、let、packages、private、protected、public。 静态和屈服