2011-07-05 21 views
11

首先,我很抱歉,如果這是重複的,但每次我搜索'對象'和'代碼'我有教程頁。Javascript對象獲得代碼作爲字符串

我想知道是否有任何簡單的方法來獲取與對象關聯的代碼。類似於

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*/);" 

但是,因爲大多數你已經知道,所有得到的輸出都是類似「Object」的東西。我幾乎找到解決的辦法,通過將初始化函數中,像這樣

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我想要使代碼是動態可執行和高度模塊化。我正在處理畫布。我希望用戶能夠點擊例如矩形,查看其代碼,然後修改並加載/執行它。我有一系列的規則,但基本上我有一個形狀類,所有定義該形狀(顏色,透明度,填充,筆畫...)的東西必須作爲參數傳遞給對象構造函數,如下所示:

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)不能保證用戶會記得包裝包裝功能,因爲它對繪圖而言是完全不必要的。我正在想辦法讓包裝看起來很自然,但我想不出任何。但是,我再一次沒有睡過三十個小時。

+1

+1僅供參考Kaiser Sauze ...雖然我認爲這是拼寫KeyserSöze;-) –

+0

@Jason:我永遠不會記得如何拼寫它,所以當我把我的號碼給女士們時,我會去Rolo Tomasi ;-) – puk

回答

1

我不能相信沒有人提出這個建議(我很抱歉,如果這個答案是在兩行之間的某個地方)。我沒有想到它,因爲在發展的時候,我所有的工作都是客戶。我真正需要做的就是使用Ajax將代碼加載一次。一旦它被加載並創建了一個對象,我將它作爲一個字符串再次加載並將其分配給對象中的一個變量。

17

OK ...再次檢查...我認爲這就是你想要的;-)。

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

哇,這實際上是超級酷。我通常抨擊JavaScript是因爲它完全不如Python,但在這種情況下,它贏了。不幸的是,這不是我想要的。我現在意識到這是一個愚蠢的問題b/c對象沒有字符串表示。我要麼將所有東西都重新實現爲一個班級,要麼找到另一種方式去做。不過謝謝。 – puk

+0

我也可以將對象初始化放入函數中,然後調用字符串。 – puk

+0

我想我會編輯這個問題來更新所有感興趣的人。另外,出於某種原因,當我在美國隊時,它並沒有出現。 – puk

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/

+0

我不認爲這就是我正在尋找的東西,我想要的是原來的代碼,而不僅僅是屬性。 – puk

+0

這將顯示功能,屬性等,但他們每個人分開。你可以調整它,所以每個循環都將一些東西添加到一個字符串中,而不是提醒它。其實讓我改變它... –

+0

丹尼爾,謝謝你的jsfiddle。它絕對清除了東西:) – puk

3

編輯:添加漂亮的印刷。

您可以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()); 

輸出是:

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); 
    } 
}) 
+0

哇,我沒有想到這麼多答案。也許我應該解釋我爲什麼首先提出這個問題。我會再次編輯。 – puk

+0

我再次編輯我的問題。我解釋了爲什麼我需要它,爲什麼我不僅需要對象的結構,而且需要代碼本身的結構。因此,出於美學原因,我需要製表符,空格和換行符。否則,用戶將輸入一些內容並保存,然後當他們重新打開時,所有的代碼突然全部平鋪爲一行代碼 – puk

+0

您無法恢復原始空間,製表符和換行符,除非代碼首先保存爲字符串(實際上可能是最容易遵循的路徑)。我編輯了我的答案,以提高輸出的美感。然而,這個'toString()'實際上是用我的縮進樣式重新縮進的(四個空格縮進,':'之前沒有空格),儘管代碼最初是使用你的樣式輸入的。你顯然可以編輯'toString()'來適應你的風格。 –

0

聽起來你正在尋找的反思和/或自檢支持。我不確定其他主要引擎在這方面的位置,但SpiderMonkey的Parser API最近在有關Extension Introspection with Chrome Privileges的文章中被引用。

+0

我回避使用解析器,因爲我對它們幾乎沒有任何經驗,但我可能不得不開始。我想要的另一件事是將每個函數存儲爲一個文件,然後將它們加載到index.html中(或者只要其中一個子文件被更改並且只加載index.html中的文件,將其合併到一個.js文件中),然後讓該文件生成的每個對象都知道文件路徑。 – puk

+0

是否有我的AT(@)標誌沒有顯示的原因?我不能再以@ user(@user)的形式回覆特定的用戶。語法是否改變了,還是我不小心改變了我的設置?例如,我試着用'@ psema4'開始我以前的評論,但我沒有看到它 – puk

+0

感謝鏈接psema4。我將用它作爲非對象部分(即類和整個腳本) – puk

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); 
1

參考下面的代碼片段:

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

 
a = new A(); 
 

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

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

當你這樣做new A()function A成爲對象a的構造。因此,您可以通過對象aconstructor屬性參考function A

Read more about Javascript constructor on MDN