严格模式
描述
- 严格模式可以分别作用在全局作用域中和函数作用域中
-
严格模式是对JavaScript代码的一种限制方式
- 严格模式可以将不明确显示的错误转变成明确显示
- 严格模式可以修正一些解释器难以优化的错误
严格模式下的变量
禁止意外创建变量
-
没有开启严格模式时
- 在调用该变量时,不会报错
- 解释器会自动补全 var关键字
-
开启严格模式时
- 在调用该变量时,会报错
- 显示 ReferenceError: s is not defined
/* 开启严格模式 - 全局作用域 */
"use strict";
/* 定义一个变量 - 不使用 var关键字 */
s = 100;
/*
没有开启严格模式时
* 在调用该变量时,不会报错
* 解释器会自动补全 var关键字
开启严格模式时
* 在调用该变量时,会报错
* 显示 ReferenceError: s is not defined(该变量没有被定义)
*/
console.log( s );// 显示 100 - 开启严格模式后的显示 s is not defined(报错)
* 定义一个函数 */
function fun() {
/* 定义一个变量 - 不使用var关键字 */
s = 100;
console.log( s );
}
/* 调用函数 */
fun();// 显示 100
/*
在未开启严格模式的情况下
* 在函数作用域中,不使用var关键字定义的变量,会自动从局部变量提升到全局变量
在开启严格模式的情况下
* 在函数作用域中,不使用var关键字定义的变量,会报错
*/
/* 在全局作用域访问函数作用域中的局部变量 */
console.log( s );// 显示 100 开启严格模式后的显示 ReferenceError: s is not defined(报错)
静默失败转为异常
- 静默表示既不报错也不显示任何效果
- 在严格模式下,静默失败会转为报错
/* 开启严格模式 */
"use strict";
/* 定义一个常量 */
const c = 100;
/* 对常量重新赋值 */
c = 200;
/* 开启严格模式后会将静默失败转成报错 */
console.log( c );// 显示 TypeError: Assignment to constant variable.
禁用delete关键字
- 在非严格模式下,对变量使用delete 会静默失败
- 在严格模式下,对变量使用delete 会报错
/* 开启严格模式 */
"use strict";
/* 定义一个变量 */
var s = 100;
/*
对变量使用delete
* 在非严格模式下delete 会无效
* 在严格模式下会报错 SyntaxError: Delete of an unqualified identifier in strict mode.
*/
delete s;
/* 在调用该变量 */
console.log( s );// 显示 100 ,在严格模式下会报错 Delete of an unqualified identifier in strict mode.
对变量名的限制
- 在非严格模式下,定义变量名时,使用保留字,会正常显示或静默失败
- 在严格模式下,定义变量名是,使用保留字,会报错
/* 开启严格模式 */
"use strict";
/* 定义一个变量 - 使用保留字定义变量名 */
var let = 100;
console.log( let );
/*
非严格模式 显示 100
严格模式 显示 SyntaxError: Unexpected strict mode reserved word
*/
严格模式下的对象
不可删除的属性
- 在非严格模式下,使用delete去删除不可删除的属性时,会静默失败
- 在严格模式下,使用delete去删除不可删除的属性时,会报错
/* 开启严格模式 */
"use strict";
/* 使用delete 删除Object对象的原型属性 */
delete Object.prototype;
/* 在调用Object对象的原型属性 */
console.log( Object.prototype );
/*
非严格模式下 显示 {}(正常显示一个空对象)
严格模式下 显示 TypeError: Cannot delete property 'prototype' of function Object() { [native code] }
*/
属性名必须唯一
- 在非严格模式下,对象的属性名允许重复,会执行最后一次定义的内容
- 在严格模式下,对象的属性名重复时,编辑器会报错,但是会正常运行最后一次定义的内容
/* 开启严格模式 */
"use strict";
/* 定义一个对象 */
var obj = {
name : '融念冰',
name : '唐三'
}
/* 调用对象的属性 */
console.log( obj.name );
/*
非严格模式下 显示 唐三
严格模式下 显示 唐三
*/
只读属性的赋值
- 在非严格模式下,对只读属性进行从新赋值,会静默失败
- 在严格模式下,对只读属性进行重新赋值,会报错
/* 开启严格模式 */
"use strict";
/* 定义一个对象 */
var obj = {
name : '唐三'
};
/* 获取指定属性的属性描述符 - 将属性改为只读属性 */
Object.defineProperty( obj, 'name', {
/* 通过属性描述符将指定属性改为只读 */
writable : false
} );
/* 对指定属性进行修改 */
obj.name = '融念冰';
/* 调用属性 */
console.log( obj.name );
/*
非严格模式下 显示 唐三(无法修改属性)
严格模式下 显示 TypeError: Cannot assign to read only property 'name' of object '#<Object>'
*/
不可扩展的对象
- 在非严格模式下,对不可扩展的对象添加新属性,会静默失败
- 在严格模式下,对不可扩展的对象添加新属性,会报错
/* 开启严格模式 */
"use strict";
/* 定义一个空对象 */
var obj = {};
/* 将指定对象设置为不可扩展的对象 */
Object.preventExtensions( obj );
/* 为不可扩展的对象新增属性 */
obj.name = '唐三';
/* 调用对象 */
console.log( obj );
/*
非严格模式下 显示 {}(空对象)
严格模式下 显示 TypeError: Cannot add property name, object is not extensible
*/
严格模式下的函数
参数名必须唯一
- 在非严格模式下,参数名允许重复,后面匹配的参数会覆盖之前匹配的参数
- 在严格模式下,参数名重复时,编辑器会提示报错,运行时也会报错
/* 开启严格模式 */
"use strict";
/* 定义一个函数 */
function fun( a, a, b ) {
console.log( a + a + b );
}
/* 调用函数并传递参数 */
fun( 1, 2, 3 );
/*
非严格模式下 显示 7(2+2+3)
严格模式下 显示 SyntaxError: Duplicate parameter name not allowed in this context
*/
arguments的不同
- 在非严格模式下,arguments对象获取参数的值与形参有关
- 严格模式下,arguments对象获取参数的值与形参无关
/* 开启严格模式 */
"use strict";
/* 定义一个函数 */
function fun( canshu ) {
/* 定义局部变量 */
var canshu = '唐三';
/* 调用局部变量 */
console.log( canshu );// 显示 唐三
/* 通过arguments获取参数 */
console.log( arguments[0] );
/*
非严格模式下 显示 唐三
* 当局部变量与参数同名时,会根据就近原则进行获取
严格模式下 显示 融念冰
* 只会获取在调用函数时传递的实参
*/
}
/* 调用函数并传递参数 */
fun( '融念冰' );
arguments对象的callee()方法
- 在非严格模式下,callee()方法表示当前调用的函数
- 在严格模式下,arguments对象将无法调用callee()方法,会报错
/* 开启严格模式 */
"use strict";
/* 定义一个函数 */
function fun() {
/* 将callee()方法返回 */
return arguments.callee;
}
/* 调用函数 */
fun();
/*
非严格模式下 显示 (由于示例代码的关系,所以没用显示)
严格模式下 显示 TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
*/
函数声明的限制
- 在非严格模式下,函数可以在任何作用域下进行定义
- 在严格模式下,函数只能在全局作用域和函数作用域下进行定义
/* 开启严格模式 */
"use strict";
/* 在全局作用域定义函数 */
function fun() {
/* 在函数作用域定义内部函数 */
function fn() {
}
}
/* 在 ES6 中新增了一个新的作用域 - 块级作用域 */
for ( var i = 0 ; i < 10; i++ ) {
// 该语句块中就为块级作用域
/* 在块级作用域中定义函数 */
function f() {
console.log( '三步白头' );
}
}
/* 调用函数 f */
f();
/*
非严格模式下 显示 三步白头
严格模式下 显示 报错ReferenceError: f is not defined
*/
严格模式下的特殊值
增加eval作用域
- 在非严格模式下,eval()函数创建的变量可以在其他位置进行调用
- 在严格模式下,eval()函数创建的变量只能在当前eval()函数中使用,其他位置调用会报错
/* 开启严格模式 */
"use strict";
/* 定义eval()函数 */
eval( "var s = '三步白头'" );
/* 调用eval()函数中变量 */
console.log( s );
/*
非严格模式下 显示 三步白头
严格模式下 显示 报错ReferenceError: s is not defined
*/
禁止读写
- 在非严格模式下,使用 eval 或 arguments 做为标识符(变量名、函数名、对象名)时,会静默失败
- 在严格模式下,使用 eval 或 arguments 做为标识符(变量名、函数名、对象名)时,会报错
/* 开启严格模式 */
"use strict";
/* 使用 eval 或 arguments 做为标识符 */
eval = 17;
arguments++;
++eval;
var obj = { set p(arguments) { } };
var eval;
try { } catch (arguments) { }
function x(eval) { }
function arguments() { }
var y = function eval() { };
var f = new Function("arguments", "'use strict'; return 17;");
/*
非严格模式下 显示 没有显示
严格模式下 显示 报错 SyntaxError: Unexpected eval or arguments in strict mode
*/
抑制this
- 在非严格模式下,在函数使用apply()方法或call()方法来调用函数时,使用null或undefined来代替this的指向对象时,this会指向全局对象
- 在严格模式下,在函数使用apply()方法或call()方法来调用函数时,使用null或undefined来代替this的指向对象时,会报错
/* 开启严格模式 */
"use strict";
/* 定义全局变量 */
var s = 100;
/* 定义函数 */
function fun() {
console.log( this.s );
}
/* 使用appl()方法或call()方法来调用函数 */
fun.apply( null );
/*
非严格模式下 显示 undefined(浏览器环境下 会指向全局变量 并显示变量值 100)
严格模式下 显示 报错 TypeError: Cannot read property 's' of null
*/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。