Javascript Javascript对象以字符串形式获取代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6583330/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript object get code as string
提问by puk
First off, I am sorry if this is a duplicate, but every time I googled for 'object' and 'code' I got tutorial pages.
首先,如果这是重复的,我很抱歉,但每次我搜索“对象”和“代码”时,我都会得到教程页面。
I want to know if there is any easy way to get the code associated with an object. Something like
我想知道是否有任何简单的方法来获取与对象关联的代码。就像是
function A(){
this.name = 'Kaiser Sauze';
}
a = new A();
console.log(a.displayCode());
//OUTPUT
"function A(){ this.name = 'Kaiser Sauze';}"
I want to be able to view the code, modify it and reload the function, all from within the browser. I wanted to know if there was some way to do this, or if I have to prime the pump by doing something like this:
我希望能够在浏览器中查看代码、修改它并重新加载函数。我想知道是否有某种方法可以做到这一点,或者我是否必须通过执行以下操作来启动泵:
function A(){
this.name = 'Kaiser Sauze';
this.code = "function A(){ this.name = 'Kaiser Sauze';}"
}
then every time the user loads up the text editor to view this.code
I connect the onchange to update this.code
.
然后每次用户加载文本编辑器进行查看时,this.code
我都会将 onchange 连接到 update this.code
。
EDIT
编辑
turns out yankee suggested a simple solution to this
结果 yankee 提出了一个简单的解决方案
function A(x){
this.x = x ;
}
console.log(A.toString());
//OUTPUT
"function A(x){
this.x = x ;
}"
but in my implementation the variable 'x' can be a function (actually a complicated object with variables, functions and sub objects which I mix in via a call to dojo.mixin), so what I really want is to know the code when instantiated, something like so
但在我的实现中,变量“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*/);"
but, as most of you already know, all that gets output is something like "Object". I have almost found a way around this, by putting the initialization in a function like so
但是,正如你们大多数人已经知道的那样,所有获得输出的都是类似“对象”的东西。我几乎找到了解决这个问题的方法,将初始化放在像这样的函数中
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*/);
}"
but that is confusing, and then I have to go in and start parsing the string which I do not want to do.
但这令人困惑,然后我必须进入并开始解析我不想做的字符串。
EDIT: The reason I ask all of this is b/c I want to make code that is both dynamically executable and highly modular. I am dealing with the canvas. I want the user to be able to click on a, for example, rectangle, view its code, and modify and then load/execute it. I have a series of rules but basically I have a shape class and everything that defines that shape (color, transparency, fills, strokes...) has to get passed as a parameter to the object cosntructor, something like:
编辑:我问这一切的原因是 b/c 我想制作既可动态执行又高度模块化的代码。我正在处理画布。我希望用户能够点击一个矩形,查看它的代码,修改然后加载/执行它。我有一系列规则,但基本上我有一个形状类,定义该形状的所有内容(颜色、透明度、填充、笔触...)都必须作为参数传递给对象构造函数,例如:
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);
}
});
This way the code is automatically modular, I don't have to worry about the color being defined at the top of the page, and then the height being defined half way down the page, and so on. Now the only thing I need is to somehow, pass as a parameter, the entire above string representation of the initialization. I could wrap it in a function and call toString on that, like so
这样代码自动模块化,我不必担心在页面顶部定义颜色,然后在页面中间定义高度,等等。现在我唯一需要的是以某种方式将初始化的整个上述字符串表示作为参数传递。我可以将它包装在一个函数中并调用 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()
});
}
but then there are two problems. 1) I have to manually remove the function wrapper()
and trailing }
as well as moving every line to the left by one tab. 2) there is no guarantee that a user will remember to include the wrapper function as it is totally unecessary for purposes of drawing. I am trying to think of a way where the wrapper would seem natural, but I can't think of any. But then again I haven't slept in over 30 hours.
但是有两个问题。1)我必须手动删除function wrapper()
和尾随}
以及将每一行向左移动一个选项卡。2) 不能保证用户会记得包含包装函数,因为它对于绘图目的是完全没有必要的。我试图想出一种包装看起来很自然的方法,但我想不出任何方法。但话又说回来,我没有睡超过 30 小时。
采纳答案by puk
I can't believe no one suggested this (I apologize if this answer is somewhere in between the lines). I didn't think of it because at the time of development, all my work was clientside. All I really have to do is load the code once with Ajax as javascript. Once it is loaded and an object created, I load it again as a string and assign it to a variable in the object.
我不敢相信没有人提出这个建议(如果这个答案介于两者之间,我深表歉意)。我没有想到,因为在开发的时候,我所有的工作都是客户端。我真正需要做的就是使用 Ajax 作为 javascript 加载一次代码。加载并创建对象后,我将其作为字符串再次加载并将其分配给对象中的变量。
回答by yankee
OK... Reviewing again... I think that's what you want ;-).
好的......再次......我认为这就是你想要的;-)。
>>> function A() {this.name ="foo";}
undefined
>>> A.toString()
"function A() {this.name ="foo";}"
回答by Edgar Bonet
Edit: added pretty-printing.
编辑:添加漂亮的印刷。
You could JSON.stringify()
the argument of the constructor, if it is JSON-compatible. Here is a toString()
function that builds on this idea, but with a slightly generalized version of JSON.stringify()
that accepts stringifying functions:
您可以JSON.stringify()
使用构造函数的参数,如果它与 JSON 兼容。这是一个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());
The output is:
输出是:
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);
}
})
回答by Roy
Here is another solution that might work (using yankee's example). I am however unsure what happens if A already exists? Perhaps you should do a "delete(A);" before saving it in the storage.
这是另一个可能有效的解决方案(使用 yankee 的示例)。但是,我不确定如果 A 已经存在会发生什么?也许你应该做一个“delete(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);
回答by Daniel Gruszczyk
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;
// }
Here is my fiddle for that: http://jsfiddle.net/DanielDZC/vXrQf/
这是我的小提琴:http: //jsfiddle.net/DanielDZC/vXrQf/
回答by cychoi
Refer to code snippet below:
参考下面的代码片段:
function A() {
this.name = 'Kaiser Sauze';
}
a = new A();
console.log(a.constructor.toString());
// output
// "function A(){
// this.name = 'Kaiser Sauze';
// }"
When you do new A()
, function A
becomes the constructor of object a
. Thus, you can reference function A
via the constructor
property of object a
.
当你这样做时new A()
,function A
就成为 object 的构造函数a
。因此,您可以function A
通过constructor
object的属性进行引用a
。
回答by psema4
Sounds like you're looking for Reflection and/or Introspection support. I'm not sure where the other major engines are at in this regards but SpiderMonkey's Parser APIwas recently referenced in an article on Extension Introspection with Chrome Privileges.
听起来您正在寻找 Reflection 和/或 Introspection 支持。我不确定其他主要引擎在这方面的位置,但最近在一篇关于扩展自省与 Chrome 特权的文章中引用了SpiderMonkey 的解析器 API。
回答by IQAndreas
I wouldn't recommend using on a production server, only for testing and debugging, but there is a method named toSource()
which returns the source of a function as a String:
我不建议在生产服务器上使用,仅用于测试和调试,但有一个名为的方法将toSource()
函数的源作为字符串返回:
function add(a, b) {
return a + b;
}
console.log(add.toSource());
Outputs:
输出:
function add(a, b) { return a + b; }
Available on JS Fiddle: http://jsfiddle.net/IQAndreas/dP453/1/
在 JS Fiddle 上可用:http: //jsfiddle.net/IQAndreas/dP453/1/
Note that Mozilla has marked this method as non-standard(which if you read the detailsmeans "Only works in FireFox").
请注意,Mozilla 已将此方法标记为非标准(如果您阅读详细信息,则表示“仅适用于 FireFox”)。