JavaScript起点(严格模式深度了解)


Posted in Javascript onJanuary 28, 2013

严格模式(Strict Mode)是ECMAScript5新增的功能。ECMAScript5虽然可以向后兼容ECMAScript3,但如果使用严格模式,哪些ECMAScript5“不在建议使用”的ECMAScript3语法功能将会被全部进制,如果出现就会抛出一行。引入Strict Mode目的是允许开发人员能够选择“更好”的Javascript版本,这个版本能用不同的方式处理那些普遍而又臭名昭著的错误。目前所有的主流浏览器的最新版本——包括IE10与Opera12——都支持严格模式。关于严格模式的大多数信息都可以在《ES5规范》[PDF]的第223页找到。

如何启用严格模式
可以在全局范围内使用严格模式,也可以在一个函数范围内使用严格模式。如果要再全局范围内启用严格模式,只需要在程序的第一行使用代码即可:

'use strict';

在函数的内部启用严格模式,只需要在函数体内第一行使用代码即可:
function imStrict(){ 
'use strict'; 

// ... 其他代码 ... 
}

启用严格模式的语句只是一段普通的字符串“use strict”,没有任何新语法。这意味着不会对就旧式浏览器造成任何负面影响,因此可以大胆使用。

在函数内部启用严格模式的一个实际应用是,把整个Javascript类库定义在严格模式的函数内部,这样就可以不影响外部的代码:

(function(){ 
"use strict"; 

// Define your library strictly... 
})();

严格模式带来了什么?
在开始介绍特殊特性之前,你需要记住,严格模式的目标之一是允许更快地调试错误。帮助开发者调试的最佳途径是当确定的问题发生时抛出相应的错误(throw errors when certain patterns occur),而不是悄无声息地失败或者表现出奇怪的行为(这正是如今不在严格模式下的Javascript做的)。严格模式下的代码抛出更多的错误信 息,这是好事,因为它能帮助开发者很快注意到一些必须立即解决的问题。

去除with语句(Eliminates with)
首先,严格模式去除了with语句。当with语句出现在严格模式中时,它会被认为是非法的Javascript语句并抛出语法错误。所以,使用严格模式的第一步就是确保你没有在使用with。

// 在严格模式中将导致语法错误 
with(location){ 
alert(href); 
}

防止意外的全局变量(Prevents accidental globals)
第二点是,变量在赋值之前必须声明。在非严格模式下,给一个未声明的变量赋值将自动生成一个该名字的全局变量。这是Javascript中最普遍的错误之一。严格模式中,这样做将抛出一个错误。
// 严格模式中抛出一个错误 
(function(){ 
someUndeclaredVar ="foo"; 
}());

取消this值的强制转换(Eliminates this coercion)
另一个重要的变化是,当this值为null或undefined时,不会再将其强制转换为全局对象。也就是说,this保留了它的原始值,也因此可能会导致一些依赖于强制转换的代码发生错误。例如:
window.color ="red"; 
function sayColor(){ 
// 严格模式下,this不会指向window 
alert(this.color); 
} 
// 以下两种情况,在严格模式下都抛出错误 
sayColor(); 
sayColor.call(null);

根本而言,this值必须赋值,否则将保留undefined值。这意味着调用构造函数时若漏掉了new关键字也会导致错误:
functionPerson(name){ 
this.name = name; 
} 
// 严格模式下导致错误 
var me =Person("Nicholas");

在这段代码里,调用Person构造函数时缺少了new关键字,此时this值为undefined。由于你不能给undefined添加属性,这段代码抛出了一个错误。在非严格模式下,this会强制转换为全局对象,因此name属性能够被正确赋值为全局变量。
拒绝重复(No duplicates)
当你做了大量的编码的时候,你很容易在对象中定义了重复的属性或者给函数定义了重复的参数名。严格模式下,这两种情况都会导致错误的发生:
// 严格模式下错误 - 重复参数 
function doSomething(value1, value2, value1){ 
//code 
} 
// 严格模式下错误 - 重复属性 
var object ={ 
foo:"bar", 
foo:"baz" 
};

这两者都是语法错误,在代码执行之前将抛出错误。
更安全的eval()(Safer eval())
eval()没有被移除,但它在严格模式下发生了一些变化。最大的改变是:在eval()语句中声明的变量以及函数不会在包含域中创建。例如:
(function(){ 
eval("var x = 10;"); 
// 非严格模式下,x为10 
// 严格模式下,x没有声明,抛出一个错误 
alert(x); 
}());

任意由eval()创建的变量或函数仍呆在eval()里。然而,你可以通过从eval()中返回一个值的方式实现值的传递:
(function(){ 
var result =eval("var x = 10, y = 20; x + y"); 
// 严格模式与非严格模式下都能正常工作(得到30) 
alert(result); 
}());

不可改变引发的错误(Errors for immutables)
ECMAScript 5 同时引入了修改属性特征的能力,例如设置一个属性为只读或者冻结整个对象的结构(freezing an entire object's structure)。在非严格模式下,试图修改一个不可变的属性时将悄无声息地失败。你可能在使用一些原生APIs的时候已经遇到这类问题。严格模式将 保证无论你在何时试图使用一种不被允许的方式修改一个对象或对象的属性时抛出错误。
var person ={}; 
Object.defineProperty(person,"name"{ 
writable:false, 
value:"Nicholas" 
}); 
// 非严格模式下将悄无声息地失败,严格模式则抛出错误 
person.name ="John";

这个例子中,name属性被设置为只读。在非严格模式下,对name的赋值将悄无声息地失败;而在严格模式下,一个错误将被抛出。

:如果你在使用ECMAScript属性能力(the ECMAScript attribute capabilities),我强烈推荐你开启严格模式。如果你在改变对象的可变性(mutability of objects),你将遇到一堆错误,而它们在非严格模式下将被安静地带过。

Javascript 相关文章推荐
clientX,pageX,offsetX,x,layerX,screenX,offsetLeft区别分析
Mar 12 Javascript
Underscore.js 的模板功能介绍与应用
Dec 24 Javascript
javascript移出节点removeChild()使用介绍
Apr 03 Javascript
JS常用字符串处理方法应用总结
May 22 Javascript
jQuery手机浏览器中拖拽动作的艰难性分析
Feb 04 Javascript
JQuery悬停控制图片轮播——代码简单
Aug 05 Javascript
js获取css的各种样式并且设置他们的方法
Aug 22 Javascript
Vee-Validate的使用方法详解
Sep 22 Javascript
JQuery中queue方法用法示例
Jan 31 jQuery
Vue注册组件命名时不能用大写的原因浅析
Apr 25 Javascript
微信小程序:报错(in promise) MiniProgramError
Oct 30 Javascript
如何用vue实现网页截图你知道吗
Nov 17 Vue.js
一个页面元素appendchild追加到另一个页面元素的问题
Jan 27 #Javascript
JavaScript转换农历类实现及调用方法
Jan 27 #Javascript
Extjs中TabPane如何嵌套在其他网页中实现思路及代码
Jan 27 #Javascript
Extjs中的GridPanel隐藏列会显示在menuDisabled中解决方法
Jan 27 #Javascript
jQuery ajax serialize()方法的使用以及常见问题解决
Jan 27 #Javascript
js中parseFloat(参数1,参数2)定义和用法及注意事项
Jan 27 #Javascript
Js 冒泡事件阻止实现代码
Jan 27 #Javascript
You might like
解析:通过php socket并借助telnet实现简单的聊天程序
2013/06/18 PHP
PHP面向对象之旅:深入理解static变量与方法
2014/01/06 PHP
php 使用GD库为页面增加水印示例代码
2014/03/24 PHP
PHP中使用TCPDF生成PDF文档实例
2014/07/01 PHP
php内存缓存实现方法
2015/01/24 PHP
php-app开发接口加密详解
2018/04/18 PHP
利用了jquery的ajax实现二级联互动菜单
2013/12/02 Javascript
JQuery each()嵌套使用小结
2014/04/18 Javascript
在Node.js中使用HTTP上传文件的方法
2015/06/23 Javascript
纯javascript响应式树形菜单效果
2015/11/10 Javascript
跟我学习javascript解决异步编程异常方案
2015/11/23 Javascript
AngularJS入门之动画
2016/07/27 Javascript
vue子组件使用自定义事件向父组件传递数据
2017/05/27 Javascript
NodeJS实现图片上传代码(Express)
2017/06/30 NodeJs
浅谈Node.js ORM框架Sequlize之表间关系
2017/07/24 Javascript
vue刷新和tab切换实例
2018/02/11 Javascript
JS阻止事件冒泡的方法详解
2019/08/26 Javascript
Vue Object.defineProperty及ProxyVue实现双向数据绑定
2020/09/02 Javascript
仅利用30行Python代码来展示X算法
2015/04/01 Python
python中__call__内置函数用法实例
2015/06/04 Python
Python实现将doc转化pdf格式文档的方法
2018/01/19 Python
python连接PostgreSQL数据库的过程详解
2019/09/18 Python
python对Excel按条件进行内容补充(推荐)
2019/11/24 Python
Python tornado上传文件的功能
2020/03/26 Python
基于CSS3的CSS 多栏(Multi-column)实现瀑布流源码分享
2014/06/11 HTML / CSS
html5+css3气泡组件的实现
2014/11/21 HTML / CSS
Answear匈牙利:来自全球200多个知名时尚品牌
2017/04/21 全球购物
吉尔德利巧克力公司:Ghirardelli Chocolate Company
2019/03/27 全球购物
be2台湾单身男女交友:全球网路婚姻介绍的领导品牌
2019/10/11 全球购物
Can a struct inherit from another class? (结构体能继承类吗)
2014/07/22 面试题
铁路个人事迹材料
2014/01/30 职场文书
高中军训的心得体会
2014/09/01 职场文书
毕业班工作总结
2015/08/10 职场文书
2016年暑假家长对孩子评语
2015/12/01 职场文书
vue-router中hash模式与history模式的区别
2021/06/23 Vue.js
Kubernetes部署实例并配置Deployment、网络映射、副本集
2022/04/01 Servers