JavaScript的strict模式与with关键字介绍


Posted in Javascript onFebruary 08, 2014

2009年12月,ECMAScript发布了ECMAScript 5,这距离上一个版本的ECMAScript 3标准发布已经整整十年了,其间JavaScript虽然大行于web编程,ECMAScript 4却最终因为利益相关的各大厂商和组织在此语言的复杂性(即是否增加大量特性以扩展ECMAScript的功能)上的分歧而夭折,使得ECMAScript新标准的制订大大落后于编程的实践。ECMAScript 5在目标上没有那么雄心勃勃,除去新增了对JSON的支持和反射的更全面的控制,一项重要改进就是引入“严格模式”(strict mode)。在此模式下,ECMAScript的语法变得更严格,使得原先许多常见的易致错的代码不再被允许,包括强制变量声明和不允许with语句等。采用这种模式很简单,只要在脚本文件或者函数的首行添加"use strict";这样一行字符串就可以了。

笔者后知,2010年还曾写了一篇小文讨论with关键字的缺陷,随附如下。
楔子

很久很久以前,神笔马良的家乡为了纪念他要将一条马路以他的名字命名。马良没有推辞,不过提出了四个字的意见。多年以后,一位外地人来到这里,在这条马路上拦住一个当地人问路。

请问这是神马路?

对,这是神马路。

你也不知道吗?

我就是这的人,怎么会不知道。

那这是神马路?

你知道了还问什么。

我就是不知道这是神马路。

那我不是已经告诉你这是神马路了吗?

你能不能再说一遍这是神马路?

……

过后,这个当地人想起当年神笔马良的意见,恍然大悟。马良说的是——勿用简称。

A Question

One day Tom said to Wang Er, his Chinese friend,“I have a dream. I want to show myself on CCTV.”The next day Tom broke into a neighbor shop. The police didn't take much time to identify and arrest Tom because he was captured very clearly by the shop's CCTV.

The question is when Tom said his dream, he is

A) ambitious B) not ambitious C)ambiguous D) unambiguous

The right answer is B) and C).
正文

以上两个古今中外的例子说明简写有时会引起歧义。这在Javascript中也存在。有时候要反复引用一个名字很长的变量是很麻烦的,比如:

objectWithLongName1.propty1=value1;

objectWithLongName1.propty2=value2;

objectWithLongName1.propty3=value3;

objectWithLongName1.method1();

但是一个清晰的名字对于程序的可读性又是很重要的。所以Javascript提供了with语句。上面的例子可以改写成:

with (objectWithLongName1){ propty1=value1; 
propty2=value2; 
propty3=value3; 
method1(); 
}

这样省去不少敲打键盘的功夫,而且程序的结构也变得更加清晰。但是这样的简写引入了歧义,我们如何知道大括号内的名称,哪些是objectWithLongName1的属性和方法,哪些是外部变量和函数。Javascript的解析规则是,先在objectWithLongName1上查找这些名称的属性,如果没有找到,则认为它们是外部变量。用代码说明就是这样:
if(objectWithLongName1.property1!==undefined){ if(objectWithLongName1.value1!==undefined){ 
objectWithLongName1.property1=objectWithLongName1.value1; //可能1 
}else{ 
objectWithLongName1.property1=value1;//可能2 
} 
}else{ 
if(objectWithLongName1.value1!==undefined){ 
property1=objectWithLongName1.value1; //可能3 
}else{ 
property1=value1;//可能4 
} 
}

我们希望的是这四种可能性之一,但是一不小心,程序执行的就会是另外一种可能。而且,这样的写法对于程序的读者来说也非常难解。另一方面,对于Javascript解释器,这种不确定性也影响了语言的性能。

其实只要一个小小的改进,就可以祛除这些缺陷。我们可以在省略了对象的属性前面加上点号,这样就在属性和外部变量之间加上了直观的区分,有不少其他语言就是这样做的。我们最初的例子会变成这样:

with (objectWithLongName1){ .propty1=value1; 
.propty2=value2; 
.propty3=value3; 
.method1(); 
}

在Javascript做这样的改进之前,两害相权取其轻,要尽量避免使用with语句。我们仍然可以采用一些变通的方法。
var o1= objectWithLongName1; o1.propty1=value1; 
o1.propty2=value2; 
o1.propty3=value3; 
o1.method1();

或者对于这样的情况:

objectWithLongName1.propty1= objectWithLongName2.propty1;

objectWithLongName1.propty2= objectWithLongName2.propty2;

……

objectWithLongName1.propty10= objectWithLongName2.propty10;

可以写成:

(function(o1, o2, pl){ pl.forEach(function(item){o1[item]=o2[item];}); 
})( objectWithLongName1,objectWithLongName2, [‘propty1', ‘propty2', … , ‘propty10']);
Javascript 相关文章推荐
20个最新的jQuery插件
Jan 13 Javascript
微信小程序 简单教程实例详解
Jan 13 Javascript
jQuery中的on与bind绑定事件区别实例详解
Feb 28 Javascript
vue中动态绑定表单元素的属性方法
Feb 23 Javascript
vue router动态路由下让每个子路由都是独立组件的解决方案
Apr 24 Javascript
vue、react等单页面项目部署到服务器的方法及vue和react的区别
Sep 29 Javascript
JavaScript中的事件与异常捕获详析
Feb 24 Javascript
如何阻止小程序遮罩层下方图层滚动
Sep 05 Javascript
Vue 实现登录界面验证码功能
Jan 03 Javascript
vue中组件通信详解(父子组件, 爷孙组件, 兄弟组件)
Jul 27 Javascript
Array.filter中如何正确使用Async
Nov 04 Javascript
基于vue+echarts数据可视化大屏展示的实现
Dec 25 Vue.js
jquery ajax 局部无刷新更新数据的实现案例
Feb 08 #Javascript
jquery ajax 局部刷新小案例
Feb 08 #Javascript
Jquery实现控件的隐藏和显示实例
Feb 08 #Javascript
二叉树的非递归后序遍历算法实例详解
Feb 07 #Javascript
Select标签下拉列表二级联动级联实例代码
Feb 07 #Javascript
javascript运行机制之this详细介绍
Feb 07 #Javascript
jQuery获取当前对象标签名称的方法
Feb 07 #Javascript
You might like
IIS下配置Php+Mysql+zend的图文教程
2006/12/08 PHP
探讨php中遍历二维数组的几种方法详解
2013/06/08 PHP
php实现aes加密类分享
2014/02/16 PHP
php curl中gzip的压缩性能测试实例分析
2016/11/08 PHP
PHP实现二维数组去重功能示例
2017/01/12 PHP
PHP/HTML混写的四种方式总结
2017/02/27 PHP
PHP基于自增数据如何生成不重复的随机数示例
2017/05/19 PHP
ThinkPHP5框架缓存查询操作分析
2018/05/30 PHP
Date对象格式化函数代码
2010/07/17 Javascript
Script的加载方法小结
2011/01/12 Javascript
Javascript浮点数乘积运算出现多位小数的解决方法
2014/02/17 Javascript
js实现可兼容IE、FF、Chrome、Opera及Safari的音乐播放器
2015/02/11 Javascript
原生JS实现仿淘宝网左侧商品分类菜单效果代码
2015/09/10 Javascript
原生JS实现平滑回到顶部组件
2016/03/16 Javascript
JS实现中国公民身份证号码有效性验证
2017/02/20 Javascript
移动端滑动切换组件封装 vue-swiper-router实例详解
2018/11/25 Javascript
详解vue项目中使用token的身份验证的简单实践
2019/03/08 Javascript
基于Element的组件改造的树形选择器(树形下拉框)
2020/02/27 Javascript
Postman无法正常返回结果问题解决
2020/08/28 Javascript
Vue自定义表单内容检查rules实例
2020/10/30 Javascript
[01:04]DOTA2上海特锦赛现场采访 FreeAgain遭众解说围攻
2016/03/25 DOTA
python中定义结构体的方法
2013/03/04 Python
Linux中安装Python的交互式解释器IPython的教程
2016/06/13 Python
Clarins娇韵诗美国官网:法国天然护肤品牌
2016/09/26 全球购物
美津浓巴西官方网站:Mizuno巴西
2019/07/24 全球购物
Linux如何为某个操作添加别名
2015/02/05 面试题
西式婚礼主持词
2014/03/13 职场文书
《北京的春节》教学反思
2014/04/07 职场文书
大学生军训自我鉴定范文
2014/09/18 职场文书
局领导领导班子四风对照检查材料
2014/09/27 职场文书
师德承诺书
2015/01/20 职场文书
Go语言-为什么返回值为接口类型,却返回结构体
2021/04/24 Golang
MATLAB 全景图切割及盒图显示的实现步骤
2021/05/14 Python
使用python+pygame开发消消乐游戏附完整源码
2021/06/10 Python
spring cloud eureka 服务启动失败的原因分析及解决方法
2022/03/17 Java/Android
vue生命周期钩子函数以及触发时机
2022/04/26 Vue.js