JavaScript的严格模式:
就是是JavaScript在更严格的条件下运行。
目的:
1、消除JavaScript语法的一些不合理,不严谨之处,减少一些怪异的行为。
2、消除代码运行的一些不安全之处,保证代码运行的安全。
3、提高编译器的效率,增加运行速度。
4、为未来新版本的JavaScript做好铺垫。
启动严格模式:
在代码首部加入"use strict"。
严格模式有两种:1、全局模式;2、局部模式。
全局模式:
将"use strict"放在脚本文件的第一行,否则将以正常模式打开。
<script>
"use strict";//严格模式的标志
console.log("这是全局严格模式");
</>
局部模式:
将"use strict"放到函数内的第一行,则整个函数将以严格模式运行。
function strict(){
"use strict";//严格模式的标志
return "这是严格模式。";
}
模块模式:
因为全局模式不利于文件的合并,所以更好的做法是,借用局部模式的方法,将整个脚本文件放在一个立即执行的匿名函数中。
(function (){
"use strict";
//在这里编写JavaScript代码
})();//匿名函数,立即执行。
严格模式与正常模式的区别:
1、严格模式情况下,变量都必须先用var命令声明,然后再使用。
2、正常模式下,JavaScript允许动态绑定,即某些属性和方法到底属于那个对象,不是在编译的时候确定的,而是在运行时确定的,严格模式对其做了一定限制,在某种情况下,只允许静态绑定,即属性和方法在一开始就确定属于哪个对象。
(1)禁止使用with语句。
"use strict";
var v = 1;
with(o){
v= 2;
}
关于JavaScript中的with关键字,请点击with关键字。
(2)创设eval作用域。
在正常模式下,JavaScript有两种变量作用域:全局作用域和函数作用域。而严格模式下有第三种:eval作用域。
严格模式下,eval语句本身就是一个作用域,它所生成的变量只能用于eval内部。
"use strict"//严格模式标志
var x = 2;//全局变量
console.info(eval("var x = 5; x"));// x = 5 eval作用域变量。
console.info(x);
关于console,请点击console关键字。
以下关于"eval"的操作都是非法的。
"use strict"
var obj ={}
var eval = 3
obj.eval = 1
obj.a = eval
for(var eval in obj){}
function eval(){}
function func(eval){}
var func = new Function('eval')
(3)增强的安全措施
①禁止this关键字指向全局变量。
function f(){
return !this;
}//返回false,因此"this"指向全局变量,"!this"就是false
functioon f(){
"use strict";
return !this;
}//返回true,因为在严格模式下,this的值是undefined,所以"!this"为true。
②禁止在函数内部便利调用栈。
caller、callee、arguments的调用行为都被禁止。
function f1(){
"use strict";
f1.caller;//报错
f1.arguments;//报错
};
f1();
(4)禁止删除变量。
在严格模式下无法删除变量,只有configurable设置为true的对象属性,才能被删除。
"use strict";
var x;
delete x; //语法报错
var v1 = object.create(null,'x',{
value : 1,
configurable:true
});
delete v1.x; //删除成功
(5)显式报错
正常模式下,对一个对象的只读属性进行赋值,不会报错,只会默默的失败。但严格模式下,会报错。
"use strict";
var o = {};
Object.defineProperty(o,"v",{
value:1,
writable:false
});
o.v = 2; //报错
严格模式下,对一个使用getter方法读取的属性进行赋值,会报错。
"use strict"
var o ={
get v(){return 1;}
};
o.v = 2;//报错
严格模式下,对禁止扩展的对象添加新属性,会报错。
"use strict";
var o = {};
Object.preventExtensions(o);
o.v = 1; //会报错
严格模式下,删除不可删除的属性,会报错。
"use strict";
delete Object.prototype;//报错
(6)重名错误。
①对象不能有重名的属性。
正常模式下,如果对象有多个重名的属性,最后复制的那个属性会覆盖前面的值,在严格模式下,这属于语法错误。
"use strict"
var o ={
p:1,
p:2
}; // 语法错误
②函数不能有重名的参数。
正常模式下,如果函数有多个重名的参数,可以用arguments[i]读取。在严格模式下,这属于语法错误。
"use strict";
function f(a,a,b){//语法错误
return;
}
(7)禁止八进制表示法
在正常模式下,整数的第一位如果是0,表示这就是八进制。在严格模式下,将禁止这种表示法,整数第一位为0,将报错。
"use strict";
var n =0100;//语言错误
(8)arguments对象的限制
arguments是函数的参数对象,严格模式对它的使用进行限制。
①不允许对arguments赋值。
"use strict";
arguments++;//语法错误
var obj = {set p(arguemnts)};//语法错误
try{ }catch(arguments){ }//语法错误
function arguments(){ }//语法错误
var f = new Function("arguments","'use strict';return 17;");//语法错误
②arguments不再追踪参数的变化。
function f(a){
a = 2;
return [a, arguments[0]];
}
f(1);//正常模式为[2,2]
function f(a){
"use strict";
a = 2;
return [a,arguments[0]];
}
f(1);//严格模式为[2,1]
③禁止使用arguments.callee。
这就意味着,无法在匿名函数内部调用自身。
"use strict";
var f = function f(){return arguments.callee;};
f();
(9)函数必须声明在顶层
为了与JavaScript未来的新版本接轨,严格模式只允许在全局作用域或函数作用域的顶层声明函数。即不允许在非函数的代码块内声明函数。
"use strict";
if(true){
function f(){ } //语法错误
}
for(var i = 0;i < 5;i++){
function f2(){ } //语法错误
}
(10)保留字
严格模式新增了一些保留字:implements、interface、let、package、private、protected、public、static、yield。
(11)动态绑定
①call、apply的第一个参数直接传入,不包装为对象。
以下代码中,输出依次为"string"、"number"。在非严格模式中call、apply将对值类型的'abcd'包装为对象后传入,即两次输出都为"object"。
"use strict";
function func(){
console.log(typeof this);
}
func.call('abcd');// string
func.apply(1);// number
②call、apply的第一个参数为null、undefined时,this为null、undefined。
"use strict";
function func(){
console.log(this)
}
func.call(undefined) //undefined
func.call(null) //null
③bind的第一个参数为null、undefined时,this为null/undefined。
"use strict";
function func(){
console.log(this)
}
var f1 = func.bind(null)
var f2 = func.bind(undefined)
f1(); //null
f2(); //undefined