Javascript 严格模式详解

2016-04-08  本文已影响321人  天外来人

一 严格模式的调用
两种调用方法,适用于不同的场合

1 针对整个脚本文件
将"use strict"放在脚本文件的第一行,则整个脚本都将以"严格模式"运行。(严格地说,只要前面不是产生实际运行结果的语句,"use strict"可以不在第一行,比如直接跟在一个空的分号后面。) 注意的问题:不同模式的代码文件合并成一个文件,需要注意:

<script>
  "use strict";
  console.log("这是严格模式。");
</script>
<script>
 console.log("这是正常模式。");
</script>

2 针对单个函数
将"use strict"放在函数体的第一行,则整个函数以"严格模式"运行。

function strict(){
  "use strict";
  return "这是严格模式。";
}
function notStrict() {
 return "这是正常模式。";
}

二 语法和行为改变
1 全局变量必须显式声明,没有声明就报错,报错

2 静态绑定 也就是说,某些属性和方法到底属于哪个对象,在编译阶段就确定了。这样做有利于编译效率的提高,也使得代码更容易阅读,更少出现意外。

2.1 禁止使用with 语句(自己查阅)
2.2 创设eval作用域
正常模式下,Javascript语言有两种变量作用域(scope):全局作用域和函数作用域。严格模式创设了第三种作用域:eval作用域。
正常模式下,eval语句的作用域,取决于它处于全局作用域,还是处于函数作用域。严格模式下,eval语句本身就是一个作用域,不再能够生成全局变量了,它所生成的变量只能用于eval内部

"use strict";
var x = 2;
console.info(eval("var x = 5; x")); // 5
console.info(x); // 2

3 增强的安全措施
3.1 禁止this关键字指向全局对象

function f(){    
  return !this;  
}   // 返回false,因为"this"指向全局对象,"!this"就是false
function f(){     
  "use strict";    
  return !this;  
}   // 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。

因此,使用构造函数时,如果忘了加new,this不再指向全局对象,而是报错。

function f(){
 "use strict";
 this.a = 1;
};
f();// 报错,this未定义

由于严格模式下,函数直接调用时(不使用new调用),函数内部的this表示undefined,因此可以用call、apply和bind方法,将任意值绑定在this上面。

function fun() { 
  return this;
}
fun() //undefined
fun.call(2) // 2
fun.apply(null) // null
fun.call(undefined) // undefined

3.2 禁止在函数内部遍历调用栈(查阅)

function f1(){
 "use strict";
 f1.caller; // 报错
 f1.arguments; // 报错
   return arguments.callee //报错
}
f1();

caller:返回一个对函数的引用,该函数调用了当前函数(对于函数来说,caller属性只有在函数执行时才有定义。如果函数是由顶层调用的,那么 caller包含的就是 null )。
arguments:该对象代表正在执行的函数和调用它的函数的参数。
callee:返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文。[function.]arguments.callee可选项 function参数是当前正在执行的 Function对象的名称
4 重名错误
4.1 对象不能有重名的属性
正常模式下,如果对象有多个重名属性,最后赋值的那个属性会覆盖前面的值。 严格模式下,报错
4.2 函数不能有重名的参数
正常模式下,可以用arguments[i]读取。严格模式下,这属于语法错误

5 函数必须声明在顶层
严格模式只运行在全局作用域或函数作用域的顶层声明函数,也计算,不允许在非函数的代码块内声明函数

if (true) {
 function f() { } // 语法错误
}
for (var i = 0; i < 5; i++) {
 function f2() { } // 语法错误
}

结合jsHint

"strict": true, //严格模式 参考文章(http://www.ruanyifeng.com/blog/2013/01/javascript_strict_mode.html)
"asi": true, //允许省略分号(写上这条,规避检查出很多警告)
"bitwise": true, //禁止使用位运算符,比如经常把&&写错& 规避此错误
"noarg": true, //禁止使用.caller 和 .callee (ECMS5已经禁用了此) ×
"eqeqeq": true, //禁止使用== 和 !=  强制使用=== 和 !==
"undef": true, //禁止使用不在全局变量列表中的未定义变量 ×
"curly": true, //循环或者条件语句必须使用花括号包住
"devel": true, //定义用于调试的全局变量:console,alert
"jquery": true, //定义全局暴露的jQuery库
"browser": true, //暴露浏览器属性的全局变量 如window document
"evil": true, //禁止使用eval ×

"unused": true,

关于加不加封号的问题
在asi选项说明里,jshint的文档是这样写的:There is a lot of FUD (fear, uncertainty and doubt) spread about semicolon spreaded by quite a few people in the community. The common myths are that semicolons are required all the time (they are not) and that they are unreliable. JavaScript has rules about semicolons which are followed by all browsers so it is up to you to decide whether you should or should not use semicolons in your code.
翻译如下(【】里是我添加的说明):关于分号有大量的FUD,且是由社区里的一小撮人【你知道是指谁】散布的。一个常见的流言是必须写分号,不写分号不可靠【流言的意思是不写分号会导致代码行为不确定】。实际上JS有明确的分号规则,并且所有浏览器【居然】都忠实遵守了规则。所以是否应该在你的代码里使用分号,完全可以由你自己决定【而不是由一小撮流言散布者或二逼工具强加于你】。
jslint给出的建议其实是基于“这是合法的代码,只是格式不妥”。

上一篇下一篇

猜你喜欢

热点阅读