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);
相关文章推荐
- js(javascript)中的严格模式解析
- JS的解析顺序和作用域(严格模式)
- js 严格模式
- js严格模式
- JS的解析顺序和作用域(严格模式)
- js严格模式
- js的严格模式总结
- js的解析顺序 作用域 严格模式
- JS的解析顺序和作用域(严格模式)
- js严格模式——arguments变为参数的静态副本
- js严格模式“use strict”
- JS的解析顺序和作用域(严格模式)
- JS的解析顺序和作用域(严格模式)
- DOCTYPE 严格模式与JS严格模式
- 深入浅析JS中的严格模式
- 什么是js严格模式?
- -_-#【Better JS Code】严格模式
- js之严格模式
- 原生JS(3)严格模式、变量声明、类型
- js中的严格模式use strict