JavaScript学习小结之被嫌弃的eval函数和with语句实例详解


Posted in Javascript onAugust 01, 2016

前面的话

eval和with经常被嫌弃,好像它们的存在就是错误。在CSS中,表格被嫌弃,在网页中只是用表格来展示数据,而不是做布局,都可能被斥为不规范,矫枉过正。那关于eval和with到底是什么情况呢?本文将详细介绍eval()函数和with语句

eval

定义

eval()是一个全局函数,javascript通过eval()来解释运行由javascript源代码组成的字符串

var result = eval('3+2');
console.log(result,typeof result);//5 'number'

用法

eval()只有一个参数,如果传入的参数不是字符串,它直接返回这个参数。如果参数是字符串,它会把字符串当成javascript代码进行编译。如果编译失败则抛出一个语法错误(syntaxError)异常。如果编译成功,则开始执行这段代码,并返回字符串中的最后一个表达式或语句的值,如果最后一个表达式或语句没有值,则最终返回undefined。如果字符串抛出一个异常,这个异常将把该调用传递给eval()

var num = 1;
var str = 'test';
console.log(eval(num));//1
console.log(eval(str));//ReferenceError: test is not defined 
var strLong1 = 'var x = 1;var y = 2;';
console.log(eval(strLong1),x,y);//undefined 1 2
var strLong2 = 'var x = 1; x++;';
console.log(eval(strLong2),x);//1 2

作用域

eval()使用了调用它的变量作用域环境。也就是说,它查找变量的值和定义新变量和函数的操作和局部作用域中的代码完全一样

var b = 2;
function foo(str,a){
eval(str);
console.log(a,b);
}
foo('var b = 3;',1);//1 3

别名

当通过别名调用时,eval()会将其字符串当做顶层的全局代码来执行。执行的代码可能会定义新的全局变量和全局函数,或者给全局变量赋值,但却不能使用或修改函数中的局部变量

var geval = eval; 
var x = 'global',y = 'global'; 
function f(){
var x = 'local';
eval('x += "changed";');
return x;
}
function g(){
var y = 'local';
geval('y += "changed";');
return y;
}
console.log(f(),x);//localchanged global
console.log(g(),y);//local globalchanged

[注意]IE8-浏览器通过别名调用eval()和正常调用eval()的结果相同

副作用

javascript解释器进行了大量的代码分析和优化。而eval()的问题在于,用于动态执行的代码通常不能分析,于是解释器也无法对其进行优化,这会导致性能下降

与eval()类似的有setTimeout()、setInterval()、new Function()等,这些函数都可以以字符串作为参数,在程序运行时动态执行。这种执行机制带来的好处无法抵消其性能上的损失,所以应该尽量避免使用

严格模式

由于eval()函数过于强大,严格模式对其进行了严格的限制

【1】不能通过eval()函数来创建变量或函数,但可以查询和更改其值

'use strict';
eval('var x = 1;');
console.log(x);//ReferenceError: x is not defined
'use strict';
var x = 1;
eval('x = 2;');
console.log(x);//2

【2】禁止使用eval作为标识符

'use strict';
var eval = 10;//SyntaxError: Unexpected eval or arguments in strict mode

with

定义with语句的目的主要是为了简化多次编写同一对象的工作

with语句将object添加到作用域链的头部,然后执行statement,最后把作用域链恢复到原始状态

with(object){
statement;
}

作用

在对象嵌套层次很深的时候通常会使用with语句来简化代码编写。而本质上是通过将一个对象的引用当作作用域来处理,将对象的属性当作作用域中的标识符来处理,从而创建了一个新的词法作用域

在客户端javascript中,可能会使用类似下面这种表达式来访问一个HTML表单中的元素

document.forms[0].address.value

如果这种表达式在代码中多次出现,则可以使用with语句将form对象添加到作用域链的顶层

with(document.forms[0]){
name.value = '';
address.value = '';
emai.value = '';
}

这种方法减少了大量的输入,不用再为每个属性名添加document.forms[0]前缀。这个对象临时挂载在作用域链上,当javascript需要解析诸如address的标识符时,就会自动在这个对象中查找

[注意]with语句提供了一种读取对象的属性的快捷方式,但它并不能创建对象的属性

如果对象o有一个属性x,那么下面代码给这个属性赋值为1

var o = {x:0};
with(o) x = 1;
console.log(o.x);//1

如果o中没有定义属性x,下面代码和不使用with语句的代码x=1是一模一样的。这是因为对变量x进行了LHS查询,并将1赋值给它

var o = {};
with(o) x = 1;
console.log(o.x);//undefined
console.log(x);//1

副作用

与eval类似,with语句的javascript代码非常难于优化,同时也会给调试代码造成困难,并且同没有使用with语句的代码相比,它运算得更慢

而且,如果with语句不当,还有可能造成变量泄漏,污染全局作用域的情况

var x = 1;
var o = {};
with(o){
x = 2;
}
console.log(x);//2
console.log(o.x);//undefined

严格模式

严格模式下,禁止使用with语句

//SyntaxError: Strict mode code may not include a with statement
'use strict';
var o = {};
with(o){
x = 2;
}

最后

使用eval和with会使得引擎无法在编译时对作用域查找进行优化,从而导致性能下降,代码运行变慢。因为eval和with在实际工作中很少使用,所以严格模式下的限制,对我们来说影响不大。就像比如外交部某一天发布公告,我国不再发放去牙买加的签证,牙买加虽然都听过,但大多数人这辈子都可能不去一回,所以,无所谓了。同样地,eval和with被嫌弃不嫌弃的,也是无所谓了

以上所述是小编给大家介绍的JavaScript学习小结之被嫌弃的eval函数和with语句实例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
学习YUI.Ext第五日--做拖放Darg&Drop
Mar 10 Javascript
在js(jquery)中获得文本框焦点和失去焦点的方法
Dec 04 Javascript
js时间日期格式化封装函数
Dec 02 Javascript
JavaScript异步加载浅析
Dec 28 Javascript
jQuery实现简单的点赞效果
May 29 Javascript
如何通过js实现图片预览功能【附实例代码】
Mar 30 Javascript
解决JS组件bootstrap table分页实现过程中遇到的问题
Apr 21 Javascript
Node.js配合node-http-proxy解决本地开发ajax跨域问题
Aug 31 Javascript
vue组件间通信解析
Mar 01 Javascript
JS闭包经典实例详解
Dec 20 Javascript
vue fetch中的.then()的正确使用方法
Apr 17 Javascript
在Vuex中Mutations修改状态操作
Jul 24 Javascript
jQuery简单设置文本框回车事件的方法
Aug 01 #Javascript
AngularJS基础 ng-csp 指令详解
Aug 01 #Javascript
AngularJs页面筛选标签小功能
Aug 01 #Javascript
Bootstrap Table使用方法详解
Aug 01 #Javascript
jQuery实现表格行和列的动态添加与删除方法【测试可用】
Aug 01 #Javascript
Angular 页面跳转时传参问题
Aug 01 #Javascript
AngularJS基础 ng-copy 指令实例代码
Aug 01 #Javascript
You might like
ftp类(example.php)
2006/10/09 PHP
PHP 如何获取二维数组中某个key的集合
2014/06/03 PHP
Yii2实现UploadedFile上传文件示例
2017/02/15 PHP
php array_reverse 以相反的顺序返回数组实例代码
2017/04/11 PHP
laravel-admin 在列表页添加自定义按钮的例子
2019/09/30 PHP
BOOM vs RR BO5 第二场 2.14
2021/03/10 DOTA
Jquery倒数计时按钮setTimeout的实例代码
2013/07/04 Javascript
javascript+canvas制作九宫格小程序
2014/12/28 Javascript
javascript制作的滑动图片菜单
2015/05/15 Javascript
JavaScript数组各种常见用法实例分析
2015/08/04 Javascript
jquery validate.js表单验证入门实例(附源码)
2015/11/10 Javascript
图片上传之FileAPI与NodeJs
2017/01/24 NodeJs
angular 基于ng-messages的表单验证实例
2017/05/04 Javascript
详解react-native-fs插件的使用以及遇到的坑
2017/09/12 Javascript
Vue项目全局配置微信分享思路详解
2018/05/04 Javascript
详解微信小程序实现跑马灯效果(附完整代码)
2019/04/29 Javascript
基于JS实现父组件的请求服务过程解析
2019/10/14 Javascript
vue把输入框的内容添加到页面的实例讲解
2019/11/11 Javascript
python迭代器实例简析
2014/09/25 Python
Python操作MongoDB数据库PyMongo库使用方法
2015/04/27 Python
Python实现计算最小编辑距离
2016/03/17 Python
python实现字符串加密成纯数字
2019/03/19 Python
python3 实现调用串口功能
2019/12/26 Python
python程序实现BTC(比特币)挖矿的完整代码
2021/01/20 Python
使用css3实现的windows8开机加载动画
2014/12/09 HTML / CSS
中专毕业生自荐信
2013/11/16 职场文书
展会邀请函范文
2014/01/26 职场文书
房屋买卖协议书
2014/04/10 职场文书
家长对老师的评语
2014/04/18 职场文书
奥巴马经典演讲稿
2014/09/13 职场文书
学校法制宣传日活动总结
2014/11/01 职场文书
委托函范文
2015/01/29 职场文书
安全保证书怎么写
2015/02/28 职场文书
个人维稳承诺书
2015/05/04 职场文书
教育读书笔记
2015/07/02 职场文书
Django与数据库交互的实现
2021/06/03 Python