Ruby's Louvre

每天学习一点点算法

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

访问私有变量

javascript作为一个动态语言,动态解析脚本的方法非常多,如万恶又万能的eval,低调的Function,IE独占的execScript,搭上DOM那边的script标签的text属性,W3C的script标签还能通过直接加文本节点或innerHTML解析脚本。有了这些方法,私有属性根本无处可藏。以前FF的eval更加邪恶,如果是通过模块模式构造的函数,获取其私有变量轻而易举。不过其bug已升级掉,就不说了。

说说其原理,就是内层作用域的函数可以随意访问外层作用域的变量。为此我们需要设计一个内部函数“打进”原函数的内部,不过直接修改原函数不太好,我们可以拷贝一个副本,但显然我们也用不着全单接收,只要一部分就可以。怎样只要一部分呢?所有函数都有一个叫toString的属性,我们拿它进行改造加入我们的内部函数,然后再通过动态解析复活它。

var reveal = function(fn,t){
  //用于获取目标函数的私有变量
  //作为新函数的内部函数而存在
  var get = function(t){ return eval(t); };
  //获取原函数的函数体
  var body = fn.toString().match(/function.+?\{([\s\S]*)\}/)[1];
  //新函数,有一个参数,返回目标函数的私有变量
  var newFn = Function('a','var get =' + get + '\n' +body+"\n;return get(a)");
  return newFn(t);//执行新函数
}

用法:

var parent = function(){
  var p = '私有变量';
};
var pp = dom.reveal(parent,'p');
alert(pp)//私有变量!

扩展一下,弄成一个类工厂。

  dom = {};
  dom.keys = function(obj){
    var results = [];
    for(var key in obj){
      if(obj.hasOwnProperty(key))
        results[results.length] = key;
    }
    return results;
  };
  dom.forEach = function (arr, fn, bind) {
    if (typeof arr.forEach === "function") {
      arr.forEach(fn, bind);
    } else {
      for (var i = 0,n = arr.length; i < n; i++)
        fn.call(bind, arr[i], i, arr); //bind,value,key,arr
    }
  };
  dom.reveal = function(fn){
    var get = function(target){
      return eval(target);
    };
    //获取原函数的函数体
    var body = fn.toString().match(/function.+?\{([\s\S]*)\}/)[1];
    var klass = Function('this.get =' + get + '\n' + body);
    klass.prototype = fn.prototype;//获取原函数的原型
    var keys = dom.keys(fn);//获取原函数的所有静态属性
    dom.forEach(keys,function(key){
      klass[key]= fn[key]
    });
    return klass;
  }
//****************************
 var parent = function(){
    var _p = '这是私有变量';
  };
  parent._s = "静态属性"
  parent.prototype.__p = "原型属性"
  var son = dom.reveal(parent);
  var s = new son;
  var pp = s.get('_p');
  alert(son._s)
  alert(pp)
  alert(s.__p)

如果您觉得此文有帮助,可以打赏点钱给我支付宝1669866773@qq.com ,或扫描二维码

posted on   司徒正美  阅读(2636)  评论(9编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
点击右上角即可分享
微信分享提示