Javascript严格模式详解

一、概述

1、什么是严格模式?

除了正常模式意外,ES5(2009年发布)还添加了一种模式,即“严格模式”。这种模式使javascript在更加严格的条件下运行。

2、为什么使用严格模式?

  • 消除javascript语言中一些不合理、不严谨之处,减少怪异现象;
  • 消除代码运行的一些不安全的地方,保证代码运行的安全;
  • 提高编译器效率,提高运行速度;
  • 为未来新版本的javascript打好基础;

3、怎么使用严格模式?
(1)针对整个脚本调用:

<script>
        "use strict";

</script>

"use strict" 放在所有可运行代码之前,则整个脚本将在“严格模式”下运行。

这个写法不利于函数合并,更好的方法:

 <script>
       (function(){
           "use strict";

       })();
 </script>

(2)针对单个函数:

function fn(){
"use strict";

}

"use strict"; 放在函数体所有可运行代码之前则整个函数体将在“严格模式”下运行。

二、严格模式和普通模式的区别:

1、全局变量必须显示声明

"use strict";
a=1;
console.log(a);//ReferenceError: a is not defined

2、静态绑定
javasript语言有一个特点,即允许动态绑定(某些属性和方法不是在编译时确定的,而是在运行时确定的)。
严格模式对动态绑定做出了一点限制。某些情况下,只允许静态绑定(属性和方法到底归属哪个对象,在编译阶段就应该确定)。优点:有利于编译效率的提高,也使代码更加容易阅读,更少出现意外。

(1)禁止使用with语句

"use strict";
var obj={
    name:'lwf',
    age:21
}
with(obj){//SyntaxError: Strict mode code may not include a with statement
    var name1=name;
    var age1=age;
}

另外,由于使用with语句会导致性能下降,同时也会给调试代码带来困难,因此开发过程中,不建议使用with。

(2) 创建eval作用域

正常模式下有两种作用域,即全局作用域和函数作用域,eval的作用域取决于其处于全局作用域和函数作用域。
严格模式下,会增加eval作用域。eval内生成的变量只能在eval中访问。
正常模式下:

var a=1;
var b=2;
eval("console.log(a)");//1
eval("var b=3;console.log(a)");//1
eval("console.log(b)");//3

严格模式下:

"use strict";
var a=1;
var b=2;
eval("console.log(a)");//1
eval("var b=3;console.log(a)");//1
eval("console.log(b)");//2

3、增强安全措施

(1)禁止this关键字指向全局变量

function f1(){
    console.log(!this);//false,正常模式下,this指向全局变量
}
f1();
function f2(){
    "use strict";
    console.log(!this);//true,严格模式下,this指向undefined,所以!this为true
}
f2();

(2)禁止在函数内部遍历调用栈

function f3(){
    console.log(f3.arguments);//{ '0': 1, '1': 2, '2': 3 }
}
f3(1,2,3);
function f4(){
    "use strict";
    console.log(f4.arguments);//TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.
}
f4(1,2,3);

4、禁止删除变量

正常模式和严格模式下都禁止删除变量
正常模式:

var x=4
delete x;//删除变量会直接忽略
console.log(x);//4

删除变量:

"use strict";
var y=4;
delete y;//SyntaxError: Delete of an unqualified identifier in strict mode.
console.log(y);

5、显式报错
(1)正常模式下,对一个对象的只读属性赋值,不会报错,只会默默的失败;
严格模式下,将报错。
正常模式:

 var obj3={};
 Object.defineProperty(obj3,'name',{value:1,writable:false});
 obj3.name=2;
 console.log(obj3.name);//1,没有报错

严格模式:

"use strict";
var obj4={};
Object.defineProperty(obj4,'name',{value:1,writable:false});
obj4.name=2;//TypeError: Cannot assign to read only property 'name' of object '#<Object>'
console.log(obj4.name);

(2)正常模式下,对一个使用getter方法读取的属性进行赋值,不会报错,只会默默的失败;
严格模式下,会报错

var o={
    get v(){return 1}
}
console.log(o.v);//1
o.v=2;
console.log(o.v);//1
"use strict";
var o={
    get v(){return 1}
}
console.log(o.v);//1
o.v=2;//TypeError: Cannot set property v of #<Object> which has only a getter
console.log(o.v);

(3)正常模式下,对禁止扩展的对象添加属性,不会报错,只会默默失败;
严格模式下,会报错

var o={};
Object.preventExtensions(o);
o.v=1;
console.log(o.v);//undefined
"use strict";
var o={};
Object.preventExtensions(o);
o.v=1;//TypeError: Cannot add property v, object is not extensible
console.log(o.v);

6、重名错误
(1)函数不能有重名的参数
正常模式下,如果函数有重名参数,可以使用arguments[i]读取;
严格模式下,会报错。

function fn(a,a,b){
    console.log(arguments[0]);//1
    console.log(arguments[1]);//2
    return a;
}
console.log(fn(1,2,3));//2
"use strict";
function fn(a,a,b){//SyntaxError: Duplicate parameter name not allowed in this context
    console.log(arguments[0]);
    console.log(arguments[1]);
    return a;
}
console.log(fn(1,2,3));

7、禁止八进制表示法

var n=0100;
console.log(n);//64
"use strict";
var n=0100;//SyntaxError: Octal literals are not allowed in strict mode.
console.log(n);

8、arguments对象的限制
(1)不允许对arguments对象进行赋值

function fn1(){
console.log(arguments++);//NaN
}
fn1(1,2);
"use strict";
function fn1(){
console.log(arguments++);//SyntaxError: Unexpected eval or arguments in strict mode
}
fn1(1,2);
"use strict";
var obj = { set p(arguments) { } }; // 语法错误
try { } catch (arguments) { } // 语法错误
function arguments() { } // 语法错误
var f = new Function("arguments", "'use strict'; return 17;"); // 语法错误

(2)arguments不在追踪参数的变化

function fn1(a){
    a=2;
    console.log(arguments[0],a);//2,2
}
fn1(1);
 "use strict";
function fn1(a){
    a=2;
    console.log(arguments[0],a);//1 2
}
fn1(1);

(3)禁止使用arguments.callee
这意味着无法在匿名函数里面调用自身

function fn1(){
   console.log(arguments.callee);//[Function:fn1]
}
fn1();
"use strict";
function fn1(){
   console.log(arguments.callee);//TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
}
fn1();

9、函数声明必须在顶层
严格模式下,只允许在全局作用域或函数作用域的顶层声明函数。不允许在非函数的代码块中声明函数。

if(true){
    function fn(){
        console.log(1);
    }
}
fn();
"use strict";
if(true){
    function fn(){
        console.log(1);
    }
}
fn();//ReferenceError: fn is not defined

10、保留字
严格模式下新增了一些保留字:implements, interface, let, package, private, protected, public, static, yield
使用这些词作为变量名将报错。

function fn1(){
    var let=1;
    console.log(let);
}
fn1();//1
"use strict";
function fn1(){
    var let=1;//SyntaxError: Unexpected strict mode reserved word
    console.log(let);
}
fn1();

此外,ECMAscript第五版本身还规定了另一些保留字(class, enum, export, extends, import, super),以及各大浏览器自行增加的const保留字,也是不能作为变量名的。

参考:阮一峰的JavaScript严格模式详解

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值