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 相关文章推荐
javascript tips提示框组件实现代码
Nov 19 Javascript
js动态修改input输入框的type属性(实现方法解析)
Nov 13 Javascript
js无刷新操作table的行和列
Mar 27 Javascript
js对象基础实例分析
Jan 13 Javascript
javascript实现的淘宝旅行通用日历组件用法实例
Aug 03 Javascript
javascript实现自动输出文本(打字特效)
Aug 27 Javascript
浅谈DOCTYPE对$(window).height()取值的影响
Jul 21 Javascript
浅谈javascript控制HTML5的全屏操控,浏览器兼容的问题
Oct 10 Javascript
js实现显示手机号码效果
Mar 09 Javascript
jQuery的时间datetime控件在AngularJs中的使用实例(分享)
Aug 17 jQuery
vue与原生app的对接交互的方法(混合开发)
Nov 28 Javascript
vue3使用vuedraggable实现拖拽功能
Apr 06 Vue.js
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
php完全过滤HTML,JS,CSS等标签
2009/01/16 PHP
PHP面向对象的进阶学习(抽像类、接口、final、类常量)
2012/05/07 PHP
PHP微框架Dispatch简介
2014/06/12 PHP
[原创]php实现子字符串位置相互对调互换的方法
2016/06/02 PHP
关于flash遮盖div浮动层的解决方法
2010/07/17 Javascript
javascript使用eval或者new Function进行语法检查
2010/10/16 Javascript
使用Chart.js图表库制作漂亮的响应式表单
2015/10/28 Javascript
JS Ajax请求如何防止重复提交
2016/06/13 Javascript
JS传值出现中文参数乱码的解决方法
2016/06/30 Javascript
PHP实现记录代码运行时间封装类实例教程
2017/05/08 Javascript
js实现本地图片文件拖拽效果
2017/07/18 Javascript
理解 Node.js 事件驱动机制的原理
2017/08/16 Javascript
Vue2仿淘宝实现省市区三级联动
2020/04/15 Javascript
iview日期控件,双向绑定日期格式的方法
2018/03/15 Javascript
javascript使用正则实现去掉字符串前面的所有0
2018/07/23 Javascript
vue 点击按钮实现动态挂载子组件的方法
2018/09/07 Javascript
小程序兼容安卓和IOS数据处理问题及坑
2018/09/18 Javascript
python实现超简单的视频对象提取功能
2018/06/04 Python
python numpy 一维数组转变为多维数组的实例
2018/07/02 Python
Python实现查找字符串数组最长公共前缀示例
2019/03/27 Python
python Event事件、进程池与线程池、协程解析
2019/10/25 Python
使用Python paramiko模块利用多线程实现ssh并发执行操作
2019/12/05 Python
Python super()函数使用及多重继承
2020/05/06 Python
python 基于opencv去除图片阴影
2021/01/26 Python
解析html5 canvas实现背景鼠标连线动态效果代码
2019/06/17 HTML / CSS
世界上最大的曲棍球商店:Pro Hockey Life
2017/10/30 全球购物
美国高级工作服品牌:Carhartt
2018/01/25 全球购物
Parfume Klik丹麦:香水网上商店
2018/07/10 全球购物
香港最大的洋酒零售连锁店:屈臣氏酒窖(Watson’s Wine)
2018/12/10 全球购物
高中军训广播稿
2014/01/14 职场文书
民族团结先进个人事迹材料
2014/06/02 职场文书
2015年幼儿园元旦亲子活动方案
2014/12/09 职场文书
监察建议书
2015/02/04 职场文书
法制教育讲座心得体会
2016/01/14 职场文书
如何书写授权委托书?
2019/06/25 职场文书
如何打开Win11系统注册表编辑器?Win11注册表编辑器打开修复方法
2022/04/05 数码科技