Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

eval的全局作用域问题

  废话就不多说了,我们先做一个最简单的测试,在一个匿名函数中直接使用eval var x=1;
(function(){
  var x;
  eval("x=2");
})();
alert(x);

  这个代码没问题,eval在直接使用的时候,里面的变量是局部变量。但是稍微变一点就有问题了,比如使用window.eval就有兼容性问题。 var x=1;
(function(){
  var x;
  window.eval("x=2");
})();
alert(x);

  右上角是IE8,使用window.eval在IE8-的浏览器上依然是Local作用域,而其它浏览器上是全局作用域。那么既然window.eval有这样的问题,那么和这个原理相同的eval.call当然也一样。而且更厉害的是call的第一个参数可以不传入window也行。 var x=1;
(function(){
  var x=1;
  eval.call(undefined,"x++");
  eval.call(null,"x++");
  eval.call(this,"x++");
})();
alert(x);

  既然call的第一个参数可以随便,那就意味着eval不是因为被从window对象中调用而造成全局作用域,我们再测试个代码。 var x=1;
(function(){
  var x,f=eval;
  f("x=2");
})();
alert(x);

  和上面一样,除了IE8-的浏览器都可以全局执行。这么看来eval的全局执行就不是受调用对象影响的了。不过这个方法偶尔也会用到,只是需要消耗一个变量名,通常不会这么写,而是使用表达式(1,eval)("x=2")间接调用,效果是一样的,我就不另外做测试了。既然以上这些方法在IE8-下都不能全局执行,那要怎么办呢?之前在贴吧上我有提出过一个匿名变量的概念,使用匿名变量就可以让eval在全局作用域执行,但是也只能兼容到IE7+。 var x=1;
(function(){
  var x;
  [eval][0]("x=2");
})();
alert(x);

  如果不需要兼容IE6,这个方法就可以解决问题了。但是有时候一些脑残客户就是要兼容到IE6,没办法我们就要在IE6上寻找新的处理。这里介绍两种方法,一种是使用with语句强制改变代码执行的区域,不过感觉太猥琐了,很多标准都不建议使用with。另一个方法是以毒攻毒,直接用IE Onley的execScript方法来代替eval,这个方法不错,只是需要多做一次浏览器判断。不过目前在IE6上实现全局eval还真没啥好办法。 var x=1;
(function(){
  var x=1;
  with(window)eval("x++");
  execScript("x++");
})();
alert(x);

  这篇文章就说到这儿吧,对这个eval我也没啥研究,各种嫌弃它,平时除了解析JSON就不会用到了。上面这些方法适当组合就可以全浏览器兼容了,如果有什么更好的方法请告诉我哦~
网名:
54.144.24.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^