您的位置:首页 > Web前端 > JavaScript

3.1.4 js的严格模式

2018-01-13 18:56 134 查看

JavaScript中的严格模式

摘录自:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode

原文写的非常棒,建议大家去阅读,此篇作为自己的阅读笔记

将拼写错转成异常

这个我的理解是,对于变量不能不声明就直接使用,在非严格模式下,就相当于无意创建了一个全局变量,在严格模式下是不允许的,这样做会报Uncaught ReferenceError

"use strict";

testing = true;
//Uncaught ReferenceError: testing is not defined at <anonymous>:2:9


静默失败的赋值操抛出异常

对没有写权限的属性、对只读的属性、对不可扩展的对象的新属性进行赋值操作均会报Uncaught TypeError

"use strict";

NaN = 0;
//Uncaught TypeError: Cannot assign to read only property 'NaN' of object '#<Window>'

var testObj1 = Object.defineProperty({}, "x", {value: "xTest", wirtable: false});
testObj1.x = "xxTest";
//Uncaught TypeError: Cannot assign to read only property 'x' of object '#<Object>'

var testObj2 = {get y(){return "yTest";}}
testObj2.y = "yyTest";
//Uncaught TypeError: Cannot set property y of #<Object> which has only a getter

var testObj3 = {};
Object.preventExtensions(testObj3);
testObj3.x = "zTest";
//Uncaught TypeError: Cannot add property x, object is not extensible


试图删除不可删除的属性

在非严格模式下,删除不可删除的属性时会返回false,而在严格模式下会报Uncaught TypeError类型的错误

"use strict";

delete Object.prototype;
// Uncaught TypeError: Cannot delete property 'prototype' of function Object() { [native code] }


对象的属性名不能重复

在两种模式下,都自动修复了对象

"use strict";

var o = { p: 1, p: 2 };
console.log(o)
//{p: 2}


函数的参数名唯一

这个说的是,函数的形参的名字不能够有重复的,经过测试发现,在较新的浏览器下,严格模式和非严格模式的表现是一致的都会报Uncaught SyntaxError: Duplicate parameter name not allowed in this context错误,但是在IE7-9版本下没有报错

"use strict";

function sum(a, a, c){
"use strict";
return a + b + c;
}
//Uncaught SyntaxError: Duplicate parameter name not allowed in this context


禁止八进制数字语法

非严格模式下,所有的浏览器都支持以零(0)开头的八进制语法

consle.log(0644 === 420)
//true


严格模式下,比较奇怪

IE7-9

"use strict"

consle.log(0644 === 420) //true

consle.log(0o644 === 420)
//报错:缺少 ')'


IE10-11

"use strict"

consle.log(0644 === 420)
//strict 模式下不允许使用八进制数字参数和转义字符

consle.log(0o644 === 420)
//报错:缺少 ')'


chrome(63) / firefox(57)

"use strict"

consle.log(0644 === 420)
//Uncaught SyntaxError: Octal literals are not allowed in strict mode.

consle.log(0o644 === 420)
//true


禁止设置primitive类型变量的属性

严格模式下,禁止给原子类型的变量设置属性,赋值

IE7-11

(function() {
"use strict";

false.true = "";              //TypeError
(14).sailing = "home";        //TypeError
"with".you = "far away";      //TypeError
})();
//没有报错,但是设置的属性都没有用


chrome(63) / firefox(57)

(function() {
"use strict";

false.true = "";              //TypeError
(14).sailing = "home";        //TypeError
"with".you = "far away";      //TypeError
})();
//chrome:Uncaught TypeError: Cannot create property 'true' on boolean 'false'
//firefox: TypeError: can't assign to properties of (new Boolean(false)): not an object


严格模式禁用 with

IE7-9:不管在什么模式下,都会输出1

"use strict"

var x = 17;
var obj = {x: 1}
with (
4000
obj){
console.log(x)
}
//1


IE10-11

"use strict"

var x = 17;
var obj = {x: 1}
with (obj){
console.log(x)
// 如果没有开启严格模式,with中的这个x会指向obj.x
}
//strict 模式下不允许使用“with”语句


chrome(63) / firefox(57)

"use strict"

var x = 17;
var obj = {x: 1}
with (obj){
console.log(x)
// 如果没有开启严格模式,with中的这个x会指向obj.x
}
//chrome:Uncaught TypeError: Strict mode code may not include a with statement
//firefox: SyntaxError: strict mode code may not contain 'with' statements


禁止删除声明变量

IE7-9:不管在什么模式下,都会成功的删除x,而且console.log(x)还会报错”x未定义”

"use strict"

var x = 1;
delete x;


IE10-11

"use strict"

var x = 1;
delete x;
//strict 模式下不允许对表达式调用 Delete


chrome(63) / firefox(57) (非严格模式下,删除都会失败)

"use strict"

var x = 1;
delete x;
//chrome:Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
//firefox: SyntaxError: applying the 'delete' operator to an unqualified name is deprecated


严格模式下的 eval 不再为上层范围(surrounding scope,注:包围eval代码块的范围)引入新变量

一般情况下, 在一个包含 eval 调用的函数内所有没有引用到参数或者局部变量的名称都必须在运行时才能被映射到特定的定义 (因为 eval 可能引入的新变量会覆盖它的外层变量). 在严格模式下 eval 仅仅为被运行的代码创建变量, 所以 eval 不会使得名称映射到外部变量或者其他局部变量

对于这个,我的理解是,在非严格模式下,执行到了eval里的代码,里面的变量才会影响到eval后面的代码里的重名变量的值(值覆盖),而在eval之前的代码里的重名变量是不会受到影响的,在严格模式下,eval里面的变量和外面的重名变量是互不影响的

非严格模式的测试代码:

var x = 17;
console.log(x === 17);
var evalX = eval(" var x = 42; console.log(x === 17);console.log(x === 42);x");
console.log(x === 17);
console.log(x === 42);
console.log(evalX === 42);


IE7-9

日志: true
日志: false
日志: true
日志: false
日志: true
日志: true


chrome(63)

VM81:2 true
VM82:1 false
VM82:1 true
VM81:4 false
VM81:5 true
VM81:6 true


非严格模式下,IE7-9和chrome的表现是一样,eval函数内部的变量值覆盖了外面的重名的变量

严格模式的测试代码:

var x = 17;
console.log(x === 17);
var evalX = eval("'use strict'; var x = 42; console.log(x === 17);console.log(x === 42);x");
console.log(x === 17);
console.log(x === 42);
console.log(evalX === 42);


IE7-9

日志: true
日志: false
日志: true
日志: false
日志: true
日志: true


chrome(63)

VM77:3 true
VM78:1 false
VM78:1 true
VM77:5 true
VM77:6 false
VM77:7 true


严格模式下,IE7-9的表现和它在非严格模式下是一样(没有覆盖了eval后面的变量),chrome下eval函数内部的变量值没有覆盖外面重名的变量

严格模式下将eval和arguments作为关键字

测试代码:

"use strict";
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;");


非严格模式下,这些代码在IE7-9和chrome下都不会报错

在严格模式下,IE7-9也没有报错,但是在chrome下,会报Uncaught SyntaxError: Unexpected eval or arguments in strict mode错误

严格模式下,参数的值不会随形参的值的改变而变化

严格模式下,函数的 arguments 对象会保存函数被调用时的原始参数。arguments[i] 的值不会随与之相应的参数的值的改变而变化,同名参数的值也不会随与之相应的 arguments[i] 的值的改变而变化。

测试代码:

function f(a){
a = 42;
console.log(arguments);
console.log(arguments[0]);
++arguments[0];
console.log(a);
console.log(arguments[0])
return [a, arguments[0]];
}
var pair = f(17);
console.log(pair[0] === 42);
console.log(pair[1] === 17);


IE7-9

日志: [object Arguments] {
0 : 42
}
日志: 42
日志: 43
日志: 43
日志: false
日志: false


chrome

VM132:3 [42, callee: ƒ, Symbol(Symbol.iterator): ƒ]0: 43callee: ƒ f(a)length: 1Symbol(Symbol.iterator): ƒ values()arguments: (...)caller: (...)length: 0name: "values"__proto__: ƒ ()__proto__: Object
VM132:4 42
VM132:6 43
VM132:7 43
VM132:11 false
VM132:12 false


非严格模式下,IE7-9和chrome的表现大体相同,除了一点,输出的arguments的第一个参数的值不同,在chrome下值发生了变化,而IE7-9下值还是形参的值(赋值后的)

在严格模式下,IE7-9的表现和非严格模式下一样,chrome在严格模式下,形参和arguments互不影响,而且第一个输出的arguments的第一个形参值也变化了

VM308:4 [17, callee: (...), Symbol(Symbol.iterator): ƒ]0: 18callee: (...)length: 1Symbol(Symbol.iterator): ƒ values()get callee: ƒ ()set callee: ƒ ()__proto__: Object
VM308:5 17
VM308:7 42
VM308:8 18
VM308:12 true
VM308:13 false


不再支持 arguments.callee

在严格模式下,arguments.callee 是一个不可删除属性,而且赋值和读取时都会抛出异常

测试代码:

"use strict";
var f = function() { return arguments.callee; };
f();


IE7-9在两种模式下都不会报错,chrome在非严格模式下也不会报错,在严格模式下会报Uncaught TypeError: ‘caller’, ‘callee’, and ‘arguments’ properties may not be accessed on strict mode functions or the arguments objects for calls to them

“安全的” JavaScript

第一,在严格模式下通过this传递给一个函数的值不会被强制转换为一个对象。

对于一个开启严格模式的函数,指定的this不再被封装为对象,而且如果没有指定this的话它值是undefined

一段有趣的代码:

"use strict";
function fun() { return this; }
console.assert(fun() === undefined);
console.assert(fun.call(2) === 2);
console.assert(fun.apply(null) === null);
console.assert(fun.call(undefined) === undefined);
console.assert(fun.bind(true)() === true);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: