Javascript对象将代码作为字符串获取

时间:2011-07-05 13:22:27

标签: javascript object tostring

首先,我很抱歉,如果这是重复的,但每次我搜索“对象”#39;和'代码'我有教程页面。

我想知道是否有任何简单的方法来获取与对象关联的代码。像

这样的东西
function A(){
  this.name = 'Kaiser Sauze';
}
a = new A();
console.log(a.displayCode());
//OUTPUT
"function A(){ this.name = 'Kaiser Sauze';}"

我希望能够在浏览器中查看代码,修改代码并重新加载函数。我想知道是否有某种方法可以做到这一点,或者我是否必须通过这样做来填充泵:

function A(){
  this.name = 'Kaiser Sauze';
  this.code = "function A(){ this.name = 'Kaiser Sauze';}"
}

然后,每次用户加载文本编辑器以查看this.code时,我都会将onchange连接到更新this.code

修改

结果是洋基提出了一个简单的解决方案

function A(x){
  this.x = x ;
}
console.log(A.toString());
//OUTPUT
"function A(x){
  this.x = x ;
}"

但在我的实施中,变量' x'可以是一个函数(实际上是一个带有变量,函数和子对象的复杂对象,我通过调用dojo.mixin混合在一起),所以我真正想要的是在实例化时知道代码,就像这样

function A(x){
  this.x = x ;
}
var a = new A(function(){/*DO SOMETHING*/);
console.log(a.toString());
//OUTPUT
"var a = new A(function(){/*DO SOMETHING*/);"

但是,正如你们大多数人已经知道的那样,得到输出的东西就像"对象"。通过将初始化放在像这样的函数

中,我几乎找到了解决这个问题的方法
function A(x){
  this.x = x ;
}
function _A(){
  var a = new A(function(){/*DO SOMETHING*/);
}
console.log(_A.toString());
//OUTPUT
"function _A(){
  var a = new A(function(){/*DO SOMETHING*/);
}"

但这很令人困惑,然后我必须进入并开始解析我不想做的字符串。

编辑:我问这一切的原因是b / c我想制作既可动态执行又高度模块化的代码。我正在处理画布。我希望用户能够单击例如矩形,查看其代码,然后修改然后加载/执行它。我有一系列规则,但基本上我有一个形状类,定义该形状的一切(颜色,透明度,填充,笔画......)必须作为参数传递给对象cosntructor,如:

rect = new Shape({color : 'rgba(0,0,0,1)' , 
  x : 0 , 
  y : 0 , 
  w : 100 , 
  h : 100 ,
  draw : function() {ctx.fillStyle = this.color;
    ctx.fillRect(this.x,this.y,this.w,this.h);
  }
});

这样代码是自动模块化的,我不必担心在页面顶部定义颜色,然后将高度定义在页面的一半,依此类推。现在我唯一需要的是以某种方式,作为参数传递,整个上面的字符串表示初始化。我可以将它包装在一个函数中并在其上调用toString,就像这样

function wrapper(){
  rect = new Shape({color : 'rgba(0,0,0,1)' , 
        x : 0 , 
        y : 0 , 
        w : 100 , 
        h : 100 ,
        draw : function() {ctx.fillStyle = this.color;
          ctx.fillRect(this.x,this.y,this.w,this.h);
        },
        code : wrapper.toString()
      });
  }

但是有两个问题。 1)我必须手动删除function wrapper()和尾随}以及将每一行向左移动一个标签。 2)不保证用户会记得包含包装函数,因为它对于绘图来说是完全不必要的。我试图想出一种包装看似自然的方式,但我无法想到。但是我再也没有睡过30个小时了。

8 个答案:

答案 0 :(得分:17)

好的......再次复习......我认为这就是你想要的; - )。

>>> function A() {this.name ="foo";}
undefined
>>> A.toString()
"function A() {this.name ="foo";}"

答案 1 :(得分:3)

修改:添加了漂亮的打印功能。

如果它与JSON兼容,你可以JSON.stringify()构造函数的参数。这是一个基于这个想法的toString()函数,但有一个稍微概括的JSON.stringify()版本,它接受字符串化函数:

function Shape(x){
    this.x = x;
}
Shape.prototype.toString = function() {
    function stringify(data, prefix) {
        function unicode_escape(c) {
            var s = c.charCodeAt(0).toString(16);
            while (s.length < 4) s = "0" + s;
            return "\\u" + s;
        }
        if (!prefix) prefix = "";
        switch (typeof data) {
            case "object":  // object, array or null
                if (data == null) return "null";
                var i, pieces = [], before, after;
                var indent = prefix + "    ";
                if (data instanceof Array) {
                    for (i = 0; i < data.length; i++)
                        pieces.push(stringify(data[i], indent));
                    before = "[\n";
                    after = "]";
                }
                else {
                    for (i in data)
                        pieces.push(i + ": " + stringify(data[i], indent));
                    before = "{\n";
                    after = "}";
                }
                return before + indent
                       + pieces.join(",\n" + indent)
                       + "\n" + prefix + after;
            case "string":
                data = data.replace(/\\/g, "\\\\").replace(/"/g, '\\"')
                           .replace(/\n/g, "\\n").replace(/\r/g, "\\r")
                           .replace(/\t/g, "\\t")
                           .replace(/[\x00-\x19]/g, unicode_escape);
                return '"' + data + '"';
            default:
                return String(data).replace(/\n/g, "\n" + prefix);
        }
    }
    return "new Shape(" + stringify(this.x) + ")";
};

var rect = new Shape({color : 'rgba(0,0,0,1)' , 
  x : 0 , 
  y : 0 , 
  w : 100 , 
  h : 100 ,
  draw : function() {ctx.fillStyle = this.color;
    ctx.fillRect(this.x,this.y,this.w,this.h);
  }
});
console.log(rect.toString());

输出结果为:

new Shape({
    color: "rgba(0,0,0,1)",
    x: 0,
    y: 0,
    w: 100,
    h: 100,
    draw: function() {
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.w, this.h);
    }
})

答案 2 :(得分:2)

这是另一种可行的解决方案(使用yankee的例子)。但我不确定如果A已经存在会发生什么?也许你应该做一个“删除(A);”在将其保存在存储器中之前。

// Create A
// function A() {this.name = "foo";}

var x = 'function A() {this.name = "foo";}'; // Store function to variable using A.toString();

// Save x in storage

// -- Page reload --

// Load and eval x from storage
eval(x);

var a = new A(); // Use A
alert(a.name);

答案 3 :(得分:1)

function dumpObject(obj) 
{     
    var output = "";     
    for (var i in obj) 
    {         
        var msg = i + "= " + obj[i];         
        output += msg + "\n";     
    }     
    return output; 
} 

var myObject = {
    myName: 'Daniel',

    get_name: function()
    {
        return this.myName;
    }
}

alert( dumpObject(myObject) );
//this will output:
//
//    myName= Daniel
//    get_name=function()
//    {
//        return this.myName;
//    }

这是我的小提琴: http://jsfiddle.net/DanielDZC/vXrQf/

答案 4 :(得分:1)

我无法相信没有人建议这个(如果这个答案在某些地方之间,我道歉)。我没有想到它,因为在开发时,我的所有工作都是客户端。我真正需要做的就是使用Ajax作为javascript加载代码一次。加载并创建对象后,我再次将其作为字符串加载并将其分配给对象中的变量。

答案 5 :(得分:1)

请参阅下面的代码段:

&#13;
&#13;
function A() {
  this.name = 'Kaiser Sauze';
}

a = new A();

console.log(a.constructor.toString());

// output
// "function A(){
//   this.name = 'Kaiser Sauze';
// }"
&#13;
&#13;
&#13;

执行new A()后,function A将成为对象a的构造函数。因此,您可以通过对象function A的{​​{1}}属性引用constructor

Read more about Javascript constructor on MDN

答案 6 :(得分:0)

听起来你正在寻找反思和/或内省支持。我不确定其他主要引擎在这方面的位置,但最近在Parser API的文章中引用了SpiderMonkey的Extension Introspection with Chrome Privileges

答案 7 :(得分:0)

我不建议在生产服务器上使用,仅用于测试和调试,但是there is a method named toSource()将函数的源返回为String:

function add(a, b) {
    return a + b;
}
console.log(add.toSource());

输出:

function add(a, b) { return a + b; }

JS小提琴:http://jsfiddle.net/IQAndreas/dP453/1/

请注意,Mozilla已将此方法标记为非标准(如果您read the details表示&#34;仅适用于FireFox&#34;)。