JS笔记《严格模式》

79 阅读2分钟

概述

  • 严格模式是从ES5进入标准的,主要目的是明确禁止一些不合理、不严谨的语法。消除代码运行时的一些不安全之处。
  • use strict放在脚本文件的第一行,表示整个脚本都会以严格模式运行,如果不在第一行则无效。
<script>
'use strict';  // 开启严格模式
</script>
  • use strict放在函数第一行,表示整个函数都将以严格模式运行。
function strict() {
  'use strict';
  return '这是严格模式';
}

严格模式下的错误

  • 只读属性不可写。
// 字符串设置length
'use strict';
'abc'.length = 5;  // Cannot assign to read only property 'length' of string 'abc'

// 修改只读属性
'use strict';
var obj = Object.defineProperty({}, 'a', {
  value: 37,
  writable: false
});
obj.a = 123;  // Cannot assign to read only property 'a' of object '#<Object>'

// 删除不可配置属性
'use strict';
var obj = Object.defineProperty({}, 'p', {
  value: 1,
  configurable: false
});
delete obj.p // TypeError: Cannot delete property 'p' of #<Object>
  • 只设置了取值器的属性不可写。
'use strict';
var obj = {
  get v() { return 1; }
};
obj.v = 2;  // Cannot set property v of #<Object> which has only a getter
  • 禁止扩展的对象不可扩展。
'use strict';
var obj = {};
Object.preventExtensions(obj);
obj.v = 1;  // Cannot add property v, object is not extensible
  • eval、arguments不可用做标识名。
'use strict';

// 以下语句都会报错
var eval = 17;
var arguments = 17;
var obj = { set p(arguments) { } };
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
  • 函数不能有重名的参数。
function f(a, a, b) {
  'use strict';
  return a + b;  // Duplicate parameter name not allowed in this context
}
  • 禁止八进制的前缀0表示法。
'use strict';
var n = 0100;  // Uncaught SyntaxError: Octal literals are not allowed in strict mode.

严格模式增加的安全措施

  • 变量都必须先声明,然后再使用。
'use strict';
v = 1;   // Uncaught ReferenceError: v is not defined


function f() {
  x = 123;
}
f();    // Uncaught ReferenceError: x is not defined
  • 禁止this指向全局对象。
function f() {
  'use strict';
  console.log(this === undefined); // true 正常会指向window,但严格模式下为undefined
}
f() 
  • 禁止使用 fn.caller、fn.arguments。
function f1() {
  'use strict';
  console.log(f1.caller);    // 报错
  console.log(f1.arguments); // 报错

  // Uncaught TypeError: 'caller', 'callee', and 'arguments' 
  // properties may not be accessed on strict mode functions or 
  // the arguments objects for calls to them
}
f1();
  • 禁止使用 arguments.callee。
'use strict';
var f = function () {
  return arguments.callee;
};

f(); // 报错
// Uncaught TypeError: 'caller', 'callee', and 'arguments' 
// properties may not be accessed on strict mode functions or 
// the arguments objects for calls to them
  • 禁止删除变量,如果使用delete命令删除一个变量,会报错。只有对象属性的属性描述对象的configurable属性设置为true,才能被delete命令删除。
'use strict';
var x;
delete x; // Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.

var obj = Object.create(null, {
  x: {
    value: 1,
    configurable: true
  }
});
delete obj.x; // 删除成功
  • arguments不在与形参形成映射关系。
// 正常模式
function f(a) {
  a = 2;
  return [a, arguments[0]];
}
f(1); // [2, 2]

// 严格模式
function f(a) {
  'use strict';
  a = 2;
  console.log(arguments[0]);  // 1
  arguments[0] = 3;
  console.log(a);    // 2
}
f(1);