eval详细说明,局部eval、全局eval和严格eval

1、简述

  作为解释性语言,JavaScript同样可以解释运行由JavaScript源代码组成的字符串,并产生一个值。实现的方式就是全局函数eval()。

	eval("3+2") // => 5
2、早期的eval()函数

  JavaScript语言的早期版本定义了eval()函数,eval()只有一个参数。

  如果传入的参数不是字符串,则直接返回这个参数;如果是字符串,则会当成JavaScript代码进行编译,如果编译失败则会抛出一个语法错误(SyntaxError)异常,如果编译成功,则开始执行这段代码,并返回字符串中的最后一个表达式或语句的值(没有值,则返回undefined)。

  重点是,eval()函数使用了调用它的变量作用域环境,即eval()查找变量的值和定义新变量/函数的操作跟局部作用域中的代码完全一样,即局部eval()。例如:

	var foo = function () {
		var x = 0;
		eval("x = 1");
		return x;
	}
	foo(); // => 1

  同样地,eval()函数可以通过如下代码声明一个局部函数:

	eval("function f() { return x + 1; }");

  当然,如果在最顶层代码中调用eval(),它会作用于全局变量和全局函数,即全局eval()

3、eval()函数的问题

  eval()具有更改局部变量的能力,这对于JavaScript优化器来说是一个很大的问题。因为用于动态执行的代码通常来讲是不能分析的,一般来讲,如果一个函数调用了eval(),那么JavaScript解释器将无法对这个函数做进一步优化。按照这个逻辑,如果将eval()赋值给一个变量g,那么解释器将无法优化任何调用g()的函数。

3.1 ECMAScript 3 的解决方式

  ECMAScript3不允许为eval()设置变量名,如果eval()函数通过变量名调用的话,则会抛出一个EvalError异常。

  但实际上大多数的实现并不是这么做的。当通过变量名调用时,eval()会被当成全局eval()。

3.2 ECMAScript 5 的解决方式

  ECMAScript 5是反对使用EvalError的,并且规范了eval()的行为。“直接的eval(direct eval)”调用(直接使用“eval”调用,eval看起来更像一个保留字),则被当成局部eval();使用变量名调用,则被当成全局eval()。

  IE9之前的版本和其他浏览器不同,当通过变量名调用eval()时并不是全局eval(),也不会抛出EvalError异常,而是仅仅当作局部eval()来调用。但IE定义了一个名叫execScript()的全局函数来完成全局eval()的功能(但execScript()总是返回null)。

4、严格eval()

  ECMAScript 5 严格模式(参考上一篇文章)对eval()函数的行为施加了更多限制,甚至对标识符eval的使用也施加了限制。

4.1 调用限制

  在严格模式下,或者eval()执行的代码段以"use strict"指令开始,这里的eval()是局部eval(),并且不能再局部作用域中定义新的变量或函数。

4.2 变量名限制

  严格模式将“eval”列为保留字,不能用一个变量名来覆盖eval()函数,并且变量名、函数名、函数参数或者异常捕获的参数都不能取名为“eval”。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值