展开目录
使用eval来修改上下文的变量
javascripteval缩进
X
陈尼玛的博客
记录开发生涯的踩坑经历,用时间来验证成长
加载中

eval是一个神奇的方法,可以用它来动态执行代码,以此达到常规办法做不到的事情。本文介绍使用eval来获取和修改上下文变量的办法。

请先看下面的代码:

function A(){
  var i=0;
  this.set=function(_i){
    i=_i;
  };
  this.get=function(){
    return i;
  };
}

var a=new A;
a.set(2);
console.log(a.get());

直接用this.*来赋值会导致需要增加一层的缩进。为了减少缩进,通常我会使用prototype来写。但是prototype中的方法获取不到A内部的i,以往我会把var i改成this.i,于是代码就变成了下面这样:

function A(){
  this.i=0;
}
A.prototype.set=function(_i){
  this.i=_i;
};
A.prototype.get=function(){
  return this.i;
};

var a=new A;
a.set(2);
console.log(a.get());

这样出现了一个问题,A的实例会把i作为属性暴露在外。虽然可以使用其他方式来实现外部代码无法读写i,但是我希望在A内部用局部变量的形式来保护i,这是最初需要实现的逻辑。

我想到了eval,它的用途是动态执行代码,而且被执行代码还可以获取到当前环境上下文的所有变量。那么只需要在A内部提供一个执行eval代码的接口给外部,外部代码就能方便的读写内部的东西了。

function A(){
  var i=0;

  // priv方法用于读写上下文变量
  this.priv=function(k,v){
    return eval(k+(arguments.length>1?('='+v):''));
  };
}
A.prototype.set=function(_i){
  var p=this.priv;
  p('i',_i);
};
A.prototype.get=function(){
  var p=this.priv;
  return p('i');
};

var a=new A;
a.set(2);
console.log(a.get(),a.priv); // 输出2,priv方法

但是到这一步没有完整,因为对外暴露了priv接口,外部程序还是可以对A实例的局部变量i进行读写,所以还需要一个代理层来屏蔽这个接口。


function A1(){
  var a=new A;
  for(var x in a)
    // 复制除了priv以外的属性到自身
    if(x!=='priv')(function(x,t){
      t[x]=function(){
        return a[x].apply(a,arguments);
      };
    })(x,this);
  // 返回的是a对象的影分身,具备a的一切属性,但是把priv给屏蔽了
};

m=new A1();
m.set(12);
console.log(m.get(),m.priv); // 输出12, undefined

到此算是大功告成了,以下是完整的例子,可以在浏览器控制台查看结果。

<meta charset='utf-8' />
<script>
function A(){
  var i=0;

  // priv方法用于读写上下文变量
  this.priv=function(k,v){
    return eval(k+(arguments.length>1?('='+v):''));
  };
}
A.prototype.set=function(_i){
  var p=this.priv;
  p('i',_i);
};
A.prototype.get=function(){
  var p=this.priv;
  return p('i');
};

function A1(){
  var a=new A;
  for(var x in a)
    // 复制除了priv以外的属性到自身
    if(x!=='priv')(function(x,t){
      t[x]=function(){
        return a[x].apply(a,arguments);
      };
    })(x,this);
  // 返回的是a对象的影分身,具备a的一切属性,但是把priv给屏蔽了
};

m=new A1();
m.set(12);
console.log(m.get(),m.priv); // 输出12, undefined
</script>

相关文档

暂无

随便看看

  1. windows电脑防止自动休眠

  2. git 大小写不区分问题

  3. 定长消息队列读写优化

  4. cnpm 立即同步

  5. css多行文本超出截断显示省略号

  6. react项目webpack打包时拆分异步加载的文件

  7. 华为等国产手机rem宽度超过实际宽度

  8. mac 终端运行后台程序如何在终端关闭时继续运行

  9. 搜索命令整理

  10. heroku登陆cli

  11. putty使用http代理连接服务器

  12. python下载文件,带进度条控制

  13. centos查看最近一次的开机时间

  14. mysql导出csv文件

  15. sendmail用nginx做代理

  16. mysql选取内容导出到文件

  17. 随机取某个概率区间的代码

  18. bootstrap modal弹框导致ie无法获取焦点

  19. 数据库清理优化

  20. 前端性能观察器

畅言模块加载中