严格模式
1. use strict
use strict
是一种 ECMAscript5
添加的(严格)运行模式,这种模式使得 Javascript
在更严格的条件下运行。严格模式的实现使您的程序或函数遵循严格的操作环境
严格模式对正常的JavaScript语义做了一些更改:
- 消除了
JavaScript
语法的一些不合理,不严谨之处,减少了一些怪异行为 - 消除了代码运行的一些不安全之处,保证代码运行的安全
- 提高编译器的效率,增加运行速度
- 禁用了在
ECMAScript
的未来版本中可能会定义的一些语法,为未来新版本的JavaScript
做好铺垫。比如一些保留字:class
,enum
,export
,extend
不能做变量名
2. 使用严格模式
严格模式可以应用到整个脚本或函数中。因此在使用的时候,我们可以将严格模式分为脚本开启严格模式和函数开启严格模式两种情况
2-1 为脚本开启严格模式
为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句 "use strict"
(或 'use strict'
)
// 整个脚本都开启严格模式的语法
"use strict";
var v = "Hi! I'm a strict mode script!";
2-2 为函数开启严格模式
为某个函数开启严格模式,需要在函数内部所有语句之前放一个特定语句 "use strict"
(或 'use strict'
)
function strict() {
// 函数级别严格模式语法
'use strict';
function nested() {
return "And so am I!";
}
return "Hi! I'm a strict mode function! " + nested();
}
function notStrict() {
return "I'm not strict.";
}
3. 严格模式规范
3-1 变量
- 严格模式下无法再意外创建全局变量
'use strict'
user = 'jsx';
console.log(user); // Uncaught ReferenceError: user is not defined
- 严格模式禁止删除声明变量
'use strict'
var index = 100;
delete index;
// Uncaught SyntaxError: Delete of an unqualified identifier in strict mode
- 严格模式禁止八进制数字语法
'use strict'
var num = 0o10;
console.log(num);
- 不能使用保留字 (
implements
、interface
、let
、package
、private、protected
、public
、static
和yield
标识符)作为变量名或者形参名
'use strict'
var private = 123;
var public = 'jsx'
// Uncaught SyntaxError: Unexpected strict mode reserved word
3-2 对象
- 严格模式要求一个对象内的所有属性名在对象内必须唯一
**Tips:**这个问题在
ECMAScript6
中已经不复存在
'use strict'
let obj = {
name: 'jsx',
name: 'ljj'
}
// 在 ECMAScript6中已经不复存在
console.log(obj)
- 在严格模式下, 试图删除不可删除的属性时会抛出异常
'use strict'
delete Object.prototype;
// Uncaught TypeError: Cannot delete property 'prototype' of function Object() { [native code] }
- 为只读属性赋值会抛出异常
'use strict'
let obj1 = {};
Object.defineProperty(obj1, 'user', { value: 'jsx', writable: false });
console.log(obj1)
obj1.user = 'ljj';
// Uncaught TypeError: Cannot assign to read only property 'user' of object '#<Object>'
- 对不可配置的对象的属性使用
delete
操作符会抛出异常
'use strict'
let obj2 = {};
Object.defineProperty(obj2, 'name', {value: 'jsx', configurable: false})
delete obj2.name;
console.log(obj2)
// Uncaught TypeError: Cannot delete property 'name' of #<Object>
- 对不可扩展的对象的对象添加属性会抛出异常
'use strict'
let obj3 = {};
Object.preventExtensions(obj3);
obj3.user = 'jsx'
// Uncaught TypeError: Cannot add property user, object is not extensible
3-3 函数
- 严格模式要求函数的参数名唯一
'use strict';
// 函数参数必须唯一
function sum(a, a) {
console.log(a + a)
}
sum(2, 3);
// Uncaught SyntaxError: Duplicate parameter name not allowed in this context
3-4 with
- 严格模式禁用
with
语句
'use strict'
var str = 'jsx';
var obj = {
str: 'ljj'
};
with(obj) { str };
// Uncaught SyntaxError: Strict mode code may not include a with statement
3-5 eval 和 arguments
eval()
声明变量和函数只能当前eval
内部的作用域中有效
'use strict';
function evalFn() {
eval("var x = 10");
eval('function sayhello() {console.log("hello")}')
console.log(x);
sayhello();
}
evalFn(); // ncaught ReferenceError: x is not defined
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;");
- 严格模式下,参数的值不会随
arguments
对象的值的改变而变化
'use strict';
function fn(num) {
num = 22;
console.log(num, arguments[0])
}
fn(24); // 22 24
- 不再支持
arguments.callee
'use strict'
function handle(){
console.log(arguments.callee)
}
handle();
// Uncaught TypeError: 'caller', 'callee'
3-6 this 指向
- 全局作用域的函数中的
this
不再指向全局而是undefined
- 如果使用构造函数时未添加
new
关键字,this
指向undefined
报错
'use strict';
// 严格模式下 全局函数this指向undefined
function func() {
console.log(this)
}
func(); // undefined
// 构造函数未加new关键字,this指向undefined并报错
function User() {
this.name = 'jsx'
console.log(this.name)
}
User();
// Uncaught TypeError: Cannot set properties of undefined (setting 'name')