1. "use strict"指令
1.1. "use strict"是JavaScript 1.8.5中的新指令(ECMAScript version 5)。
1.2. 它不算一条语句, 而是一段文字表达式, 更早版本的JavaScript会忽略它。
1.3. "use strict";的作用是指示JavaScript代码应该以"严格模式"执行。
1.4. 以下版本的浏览器支持严格模式:
- 版本10以后的IE
- 版本4以后的Firefox
- 版本13以后的Chrome
- 版本5.1以后的Safari
2. 声明严格模式
2.1. 通过在脚本或函数的开头添加"use strict";来声明严格模式。
2.2. 在脚本开头进行声明, 拥有全局作用域(脚本中的所有代码均以严格模式来执行):
<script type="text/javascript">
"use strict";
function myFn1(){
document.write(this + '<br />');
}
myFn1();
</script>
2.3. 同一页面中多个脚本, 可以是默认模式, 也可以是严格模式, 互不影响:
<script type="text/javascript">
"use strict";
function myFn1(){
document.write(this + '<br />');
}
myFn1();
</script>
<script type="text/javascript">
function myFn2(){
document.write(this + '<br />');
}
myFn2();
</script>
2.4. 在函数中声明严格模式, 拥有局部作用域(只有函数中的代码以严格模式执行):
function myFn3(){
"use strict";
document.write(this + '<br />');
}
myFn3();
2.5. "use strict"指令只能在脚本或函数的开头被识别。
3. 为什么使用严格模式?
3.1. 严格模式使我们更容易编写"安全的"JavaScript。
3.2. 严格模式把之前可接受的"坏语法"转变为真实的错误。
4. 严格模式中不允许的事项
4.1. 在不声明变量的情况下使用变量, 是不允许的:
<script type="text/javascript">
"use strict";
// 报错, 严格模式中, 在不声明变量的情况下使用变量, 是不允许的
a = 5;
</script>
<script type="text/javascript">
// 默认模式中, 在不声明变量的情况下使用变量, 成为全局变量
b = 10;
</script>
4.2. 使用delete删除变量是不允许的:
<script type="text/javascript">
"use strict";
var c = 15;
// 报错, 严格模式中, 使用delete删除变量, 是不允许的
delete c;
</script>
<script type="text/javascript">
var d = 20;
// 默认模式中, 使用delete删除变量, 没有任何影响
delete d;
document.write('d = ' + d + '<br />');
</script>
4.3. 使用delete删除函数是不允许的:
<script type="text/javascript">
"use strict";
function myFn1(){
document.write(this + '<br />');
}
// 报错, 严格模式中, 使用delete删除函数, 是不允许的
delete myFn1;
</script>
<script type="text/javascript">
function myFn2(){
document.write(this + '<br />');
}
// 默认模式中, 使用delete删除函数, 没有任何影响
delete myFn2;
myFn2();
</script>
4.4 重复使用参数名, 是不允许的:
<script type="text/javascript">
"use strict";
// 报错, 严格模式中, 重复使用参数名, 是不允许的
function myFn4(p1, p1){
document.write('p1 = ' + p1 + ', p1 = ' + p1 + '<br />');
}
myFn4(25, 30);
</script>
<script type="text/javascript">
// 默认模式中, 重复使用参数名, 参数值是最后一个实参的值
function myFn5(p1, p1){
document.write('p1 = ' + p1 + ', p1 = ' + p1 + '<br />');
}
myFn5(35, 40);
</script>
4.5. 八进制数值是不允许的:
<script type="text/javascript">
"use strict";
// 报错, 严格模式中, 八进制数值是不允许的
document.write('e = ' + 010 + '<br />');
</script>
<script type="text/javascript">
// 默认模式中, 八进制数值是允许的
document.write('f = ' + 020 + '<br />');
</script>
4.6. 八进制转义字符是不允许的:
<script type="text/javascript">
"use strict";
// 报错, 严格模式中, 八进制转义字符是不允许的:
document.write('\077' + '<br />');
</script>
<script type="text/javascript">
// 默认模式中, 八进制转义字符是允许的
document.write('\077' + '<br />');
</script>
4.7. 写入只读属性是不允许的:
<script type="text/javascript">
"use strict";
var obj1 = {get Id(){return this.id;}};
Object.defineProperty(obj1, 'id', {value: 1001, writable: false});
// 报错, 严格模式中, 写入只读属性是不允许的
obj1.id = 1002;
document.write('obj1.id = ' + obj1.id + '<br />');
</script>
<script type="text/javascript">
var obj2 = {get Id(){return this.id;}};
Object.defineProperty(obj2, 'id', {value: 10001, writable: false});
// 默认模式中, 写入只读属性, 不会报错, 但也不会赋值
obj2.id = 10002;
document.write('obj2.id = ' + obj2.id + '<br />');
</script>
4.8. 写入只能获取的属性是不允许的:
<script type="text/javascript">
"use strict";
var obj1 = {get Id(){return this.id;}};
Object.defineProperty(obj1, 'id', {value: 1001, writable: false});
// 报错, 严格模式中, 写入只能获取的属性是不允许的
obj1.Id = 1003;
document.write('obj1.Id = ' + obj1.Id + '<br />');
</script>
<script type="text/javascript">
var obj2 = {get Id(){return this.id;}};
Object.defineProperty(obj2, 'id', {value: 10001, writable: false});
// 默认模式中, 写入只能获取的属性, 不会报错, 但也不会赋值
obj2.Id = 10003;
document.write('obj2.Id = ' + obj2.Id + '<br />');
</script>
4.9. 删除不可删除的属性是不允许的:
<script type="text/javascript">
"use strict";
// 报错, 严格模式中, 删除不可删除的属性是不允许的
delete Object.prototype;
</script>
<script type="text/javascript">
// 默认模式中, 删除不可删除的属性, 没有任何影响
delete Object.prototype;
document.write('Object.prototype = ' + Object.prototype + '<br />');
</script>
4.10. 处于安全考虑, eval()在其被调用的作用域中创建的变量, 在其它作用域中不允许:
<script type="text/javascript">
"use strict";
eval("var drink1 = '红茶';document.write('drink1 = ' + drink1 + '<br />');");
// 报错, 严格模式中, eval()在其被调用的作用域中创建的变量, 在其它作用域中不允许
document.write('drink1 = ' + drink1 + ', window.drink1 = ' + window.drink1 + '<br />');
</script>
<script type="text/javascript">
eval("var drink2 = '绿茶';document.write('drink2 = ' + drink2 + '<br />');");
// 默认模式中, eval()在其被调用的作用域中创建的变量, 在其它作用域中可以访问, 而且它是全局变量
document.write('drink2 = ' + drink2 + ', window.drink2 = ' + window.drink2 + '<br />');
</script>
4.11. 字符串"eval"不可用作变量:
<script type="text/javascript">
"use strict";
// 报错, 严格模式中, 字符串"eval"不可用作变量
var eval = 'eval';
</script>
<script type="text/javascript">
// 默认模式中, 字符串"eval"可以用作变量
var eval = 'eval';
document.write('eval = ' + eval + '<br />');
</script>
4.12. 字符串"arguments"不可用作变量:
<script type="text/javascript">
"use strict";
// 报错, 严格模式中, 字符串"arguments"不可用作变量
var arguments = 'arguments';
</script>
<script type="text/javascript">
// 默认模式中, 字符串"arguments"可以用作变量
var arguments = 'arguments';
document.write('arguments = ' + arguments + '<br />');
</script>
4.13. with语句是不允许的:
<script type="text/javascript">
"use strict";
var book1 = "Effective Java";
// 报错, 严格模式中, with语句是不允许的
with(book1) {
document.write('book1 = ' + toUpperCase() + '<br />');
}
</script>
<script type="text/javascript">
var book2 = "Netty In Action";
// 默认模式中, with语句是允许的
with(book2) {
document.write('book2 = ' + toUpperCase() + '<br />');
}
</script>
5. 对未来的保障
5.1. 严格模式中不允许使用为未来预留的关键词。它们是:
implements
interface
let
package
private
protected
public
static
yield
6. 函数中的this(严格模式)
6.1. JavaScript严格模式不允许默认绑定。
6.2. 因此, 在函数中使用时, 在严格模式下, this是未定义的undefined。
<script type="text/javascript">
"use strict";
function myFn6(){
document.write(this + '<br />'); // 输出undefined
}
myFn6();
</script>
7. 函数中的this(默认)
7.1. 在JavaScript函数中, 函数的拥有者默认绑定this。
7.2. 因此, 在函数中, this指的是全局对象[object Window]。
<script type="text/javascript">
function myFn7(){
document.write(this + '<br />'); // 输出[object Window]
}
myFn7();
</script>
8. 例子
8.1. 代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>严格模式</title>
</head>
<body>
<script type="text/javascript">
"use strict";
function myFn1(){
document.write(this + '<br />');
}
myFn1();
// 报错, 严格模式中, 在不声明变量的情况下使用变量, 是不允许的
// a = 5;
var c = 15;
// 报错, 严格模式中, 使用delete删除变量, 是不允许的
// delete c;
// 报错, 严格模式中, 使用delete删除函数, 是不允许的
// delete myFn1;
// 报错, 严格模式中, 重复使用参数名, 是不允许的
// function myFn4(p1, p1){
// document.write('p1 = ' + p1 + ', p1 = ' + p1 + '<br />');
// }
// myFn4(25, 30);
// 报错, 严格模式中, 八进制数值是不允许的
// document.write('e = ' + 010 + '<br />');
// 报错, 严格模式中, 八进制转义字符是不允许的:
// document.write('\077' + '<br />');
var obj1 = {get Id(){return this.id;}};
Object.defineProperty(obj1, 'id', {value: 1001, writable: false});
// 报错, 严格模式中, 写入只读属性是不允许的
// obj1.id = 1002;
document.write('obj1.id = ' + obj1.id + '<br />');
// 报错, 严格模式中, 写入只能获取的属性是不允许的
// obj1.Id = 1003;
document.write('obj1.Id = ' + obj1.Id + '<br />');
// 报错, 严格模式中, 删除不可删除的属性是不允许的
// delete Object.prototype;
eval("var drink1 = '红茶';document.write('drink1 = ' + drink1 + '<br />');");
// 报错, 严格模式中, eval()在其被调用的作用域中创建的变量, 在其它作用域中不允许
// document.write('drink1 = ' + drink1 + ', window.drink1 = ' + window.drink1 + '<br />');
// 报错, 严格模式中, 字符串"eval"不可用作变量
// var eval = 'eval';
// 报错, 严格模式中, 字符串"arguments"不可用作变量
// var arguments = 'arguments';
var book1 = "Effective Java";
// 报错, 严格模式中, with语句是不允许的
// with(book1) {
// document.write('book1 = ' + toUpperCase() + '<br />');
// }
function myFn6(){
document.write(this + '<br />'); // 输出undefined
}
myFn6();
</script>
<script type="text/javascript">
function myFn2(){
document.write(this + '<br />');
}
myFn2();
function myFn3(){
"use strict";
document.write(this + '<br />');
}
myFn3();
// 默认模式中, 在不声明变量的情况下使用变量, 成为全局变量
b = 10;
var d = 20;
// 默认模式中, 使用delete删除变量, 没有任何影响
delete d;
document.write('d = ' + d + '<br />');
// 默认模式中, 使用delete删除函数, 没有任何影响
delete myFn2;
myFn2();
// 默认模式中, 重复使用参数名, 参数值是最后一个实参的值
function myFn5(p1, p1){
document.write('p1 = ' + p1 + ', p1 = ' + p1 + '<br />');
}
myFn5(35, 40);
// 默认模式中, 八进制数值是允许的
document.write('f = ' + 020 + '<br />');
// 默认模式中, 八进制转义字符是允许的
document.write('\077' + '<br />');
var obj2 = {get Id(){return this.id;}};
Object.defineProperty(obj2, 'id', {value: 10001, writable: false});
// 默认模式中, 写入只读属性, 不会报错, 但也不会赋值
obj2.id = 10002;
document.write('obj2.id = ' + obj2.id + '<br />');
// 默认模式中, 写入只能获取的属性, 不会报错, 但也不会赋值
obj2.Id = 10003;
document.write('obj2.Id = ' + obj2.Id + '<br />');
// 默认模式中, 删除不可删除的属性, 没有任何影响
delete Object.prototype;
document.write('Object.prototype = ' + Object.prototype + '<br />');
eval("var drink2 = '绿茶';document.write('drink2 = ' + drink2 + '<br />');");
// 默认模式中, eval()在其被调用的作用域中创建的变量, 在其它作用域中可以访问, 而且它是全局变量
document.write('drink2 = ' + drink2 + ', window.drink2 = ' + window.drink2 + '<br />');
// 默认模式中, 字符串"eval"可以用作变量
var eval = 'eval';
document.write('eval = ' + eval + '<br />');
// 默认模式中, 字符串"arguments"可以用作变量
var arguments = 'arguments';
document.write('arguments = ' + arguments + '<br />');
var book2 = "Netty In Action";
// 默认模式中, with语句是允许的
with(book2) {
document.write('book2 = ' + toUpperCase() + '<br />');
}
function myFn7(){
document.write(this + '<br />'); // 输出[object Window]
}
myFn7();
</script>
</body>
</html>
8.2. 效果图