2012-04-10 4 views
3

新しく作成したdivをオブジェクトのプロトタイプとして使用して、JavascriptでDIVを「拡張」しようとしています。DIV要素を拡張するときに、いくつかの要素を作成するにはどうすればよいですか?

"new"を介してオブジェクトの新しいインスタンスを作成する際に、Javascriptを理解しているので、プロトタイプオブジェクトがコピーされ、 "this"に割り当てられ、関数が(コンストラクタとして)実行されます。

他のオブジェクトを作成してDOMに追加するたびに、元のdivに "置き換えられる"ことを除いて、すべてが機能しているようです。より正確には、コンストラクタは常に同じdivを変更します。 MyTest.prototype = document.createElement("div");を使用して

は私に説明した動作を与え、二人は私も試したものですが、無駄に私のコード例ではその後の行をコメントしました。

私は眉をひそめているDOMを拡張しようとしているけど、私は、私はプロトタイプが働くと、これは単に私の考えに合わない方法を知っていたと思ったので、私は、この動作を理解したいです。ここで

は私がやろうとしています何の最小限の例です。

<!DOCTYPE html> 
<html> 
<head> 
<title>Div-Prototype-Test</title> 
<script type="text/javascript"> 

var height = 20; 
var top = 0; 

function MyTest() { 
    var r = Math.floor(Math.random() * 256); 
    var g = Math.floor(Math.random() * 256); 
    var b = Math.floor(Math.random() * 256); 

    this.style.backgroundColor = "rgb("+ r +","+ g +","+ b +")"; 
    this.style.position  = "absolute"; 
    this.style.width   = "500px"; 
    this.style.height   = height + "px"; 
    this.style.top    = top + "px"; 

    top += height; 

    document.getElementsByTagName("body")[0].appendChild(this); 
} 

MyTest.prototype = document.createElement("div"); 
// MyTest.prototype = document.createElement("div").cloneNode(true); 
// MyTest.prototype = new Element(); 

window.addEventListener(
    "load", 
    function() { 
     var a = new MyTest(); 
     var b = new MyTest(); 
     var c = new MyTest(); 
     var d = new MyTest(); 
    } 
); 

</script> 
</head> 
<body> 
</body> 
</html> 

PS:そのため、特定のJavascriptフレームワークのJavaScriptでプロトタイプを変更する何のための私の検索は、常にその結果は数百の結果私の問題とは何の関係もありませんでした。私が既にこれについて議論している質問を逃したかどうか教えてください。

編集:

私の質問をより明確にするには、次の

ここでは、私がプロトタイプとしてオブジェクトを使用する例である - そのプロパティがコピーされます。

function A() { 
} 

A.prototype = { property: 4 }; 

A.prototype.set = function(num) { 
    this.property = num; 
} 

window.addEventListener(
    "load", 
    function() { 
     var message = ""; 

     var x1 = new A(); 
     message += "A1 : "+ x1.property +"\n"; 

     x1.set(15); 
     message += "A1 : "+ x1.property +"\n"; 

     var x2 = new A(); 
     message += "A2 : "+ x2.property +"\n"; 

     alert(message); 
    } 
); 

警告、その後は言った:

A1 : 4 
A1 : 15 
A2 : 4 

私の最初の例では事業部は、しかし、それはシングルトンまたはMonostateのように振る舞い、コピーされていないようです。このようにはならないのでしょうか?

  1. PROTYPEオブジェクトは、新しいオブジェクトが、これは何のreturn文がない場合、これは(コンストラクタによって返されるコンストラクタ
  2. に与えられている「この」
  3. に割り当てられている新しいオブジェクト
  4. にコピーされます指定された)

答えて

0

私はそれが基本的には他の方法でラウンドを動作しますが、回避策を見つけた - プロトタイプは空白のオブジェクトであり、私は、コンストラクタ内のdivに新しいオブジェクトデータをコピーします。

var height = 20; 
var top = 0; 

function deepCopy(fromObject, toObject, depth) { 
    if(typeof(fromObject) != "object" || typeof(toObject) != "object") { 
     // throw "deepCopy only copies objects" 
     return; 
    } 

    if (typeof(depth) == "undefined") { 
     depth = 0; 
    } else if (depth > 100) { 
     // Recursion depth too high. Abort. 
     // throw "deepCopy recursion depth cap hit" 
     return; 
    } 

    for (var key in fromObject) { 
     if (typeof(fromObject[key]) == "object" && fromObject[key] != null) { 
      if (typeof(fromObject[key].nodeType) != "undefined") { 
       toObject[key] = fromObject[key].cloneNode(true); 
      } else { 
       if (typeof(toObject[key]) != "object") { 
        toObject[key] = {}; 
       } 
       deepCopy(fromObject[key], toObject[key], depth + 1); 
      }   

     } 
     toObject[key] = fromObject[key]; 
    } 
}  

function MyTest() { 
    // This is ugly... 
    var self = document.createElement("div"); 
    deepCopy(MyTest.prototype, self); 

    var r = Math.floor(Math.random() * 256); 
    var g = Math.floor(Math.random() * 256); 
    var b = Math.floor(Math.random() * 256); 

    self.style.backgroundColor = "rgb("+ r +","+ g +","+ b +")"; 
    self.style.position  = "absolute"; 
    self.style.width   = "500px"; 
    self.style.height   = height + "px"; 
    self.style.top    = top + "px"; 

    top += height; 

    document.getElementsByTagName("body")[0].appendChild(self); 

    return self; 
} 

MyTest.prototype = {}; 
// MyTest.prototype = document.createElement("div").cloneNode(true); 
// MyTest.prototype = new Element(); 

window.addEventListener(
    "load", 
    function() { 
     var a = new MyTest(); 
     var b = new MyTest(); 
     var c = new MyTest(); 
     var d = new MyTest(); 
    } 
); 

私はその気持ちを持っているが、私のdeepCopy関数は、タスクを実行するにはかなり面白くない(おそらく非常にバグが多い)方法ですが、cloneNode()を使ってもう一方の方法はうまくいきませんでした。

プロトタイプがコピーされると、すべてのオブジェクトが単純に参照されます(コピーポインタ、ポインタ値は重複しますが、ポインタは指し示すデータではありません)。

これは誰かを助けることを望みます。

2
MyTest.prototype = document.createElement("div"); 

この行だけ一度に実行されます。 DOM要素であるMyTest.prototypeオブジェクトを作成します<div>すべてMyTestオブジェクトはこの同じプロトタイプを受け取ります。したがって、あなたが作成するMyTestオブジェクトはすべて、あなたが作成したこの単一の<div>に関連付けられます。 MyTestごとに新しい<div>を作成する必要があります。

は、このパターンを試してみてください:

MyTest = function() { 
    var myDiv = document.createElement("div"); 

    var r = Math.floor(Math.random() * 256); 
    var g = Math.floor(Math.random() * 256); 
    var b = Math.floor(Math.random() * 256); 

    myDiv.style.backgroundColor = "rgb("+ r +","+ g +","+ b +")"; 
    myDiv.style.position  = "absolute"; 
    myDiv.style.width   = "500px"; 
    myDiv.style.height   = height + "px"; 
    myDiv.style.top    = top + "px"; 

    top += height; 

    document.getElementsByTagName("body")[0].appendChild(myDiv); 

    return myDiv; 
} 

この関数は、createElement()呼び出しを使用して、新しい<div>を作成します。次に、それはあなたが望むすべてのプロパティをその新しい<div>に設定します。最後に、新しい<div>が返されます。そのように、あなたはどちらのオプションがうまくいく

var myNewDiv = MyTest(); 
var myNewDiv = new MyTest(); 

としてそれを呼び出すことができます。 2番目のケースでは、ダミーの新しいオブジェクトがnewキーワードで作成されますが、関数内で作成された新しい<div>が実際に返されるため、問題はありません。

+0

これは私が理解していないことです。異なるオブジェクトをプロトタイプとして使用すると、そのオブジェクトとそのプロパティがコピーされます。そのプロパティの1つを変更すると、元のプロトタイプのプロパティは変更されません。 – sirion

+1

これらはコピーされません。 'MyTest.prototype'に' x'などのプロパティがあり、 'var test = new MyTest();がある場合。 test.x = 'abc'; '実際には新しい' x'プロパティを 'test'オブジェクトに追加し、プロトタイプの' x'プロパティを隠します。ただし、コードでは、すべてのオブジェクトに新しいプロパティを追加しません。すべてのインスタンスは 'style'プロパティを参照します。これはプロトタイプであり、作成した単一のdivに属します。 – Imp

+0

しかし、なぜこの原則は私の2番目の例には当てはまりませんか? (あなたがあなたの答えを書いた後に追加したもの) – sirion

0

あなたはあらゆる種類のものを混ぜています。まず、私の答えをthis SO questionにチェックしてください。次に、Elementオブジェクトを拡張することはできますが、すべてのブラウザでサポートされているわけではありません。チェックthis SO question

標準化された方法でdocumentに要素を追加する予定です。

appendElement.call(document.createElement('div'),'empty div'); 
appendElement.call(document.createElement('span'),'new empty span','span1'); 

はそれは次のようになります。

function appendElement(content,id) { 
    var rgb = 'rgb('+ [Math.floor(Math.random() * 256), 
       Math.floor(Math.random() * 256), 
       Math.floor(Math.random() * 256)].join(',') +')'; 
    var top = Math.floor(Math.random() * 300 + 20); 
    var left = Math.floor(Math.random() * 100 + 10); 

    this.style.backgroundColor = rgb; 
    this.style.position  = "absolute"; 
    this.style.width   = "500px"; 
    this.style.height   = "200px"; 
    this.style.left   = left+"px"; 
    this.style.top    = top+"px"; 
    this.innerHTML    = content || ''; 
    this.id     = id || Math.Random*10000+1 
    document.getElementsByTagName("body")[0].appendChild(this); 
} 

は今、あなたは次のように `appendElementを使用してdocumentに任意の要素を追加するためにこれを使用することができます:あなたのコードはに書き換えることができた(私はそれを少し修正しました)あなたが目指すもののアイデア?

+0

実際に私のオリジナルのアイデアは、DOMに追加の機能を持つ要素を追加することでした(今はなぜ機能しないのか理解したいだけです)。 'xxx.appendChild(new FadeDiv(urlList));'のように、urlListはイメージURLの配列です。これは、画像を背景にロードし、画像を一方から他方にフェードさせるはずです。アイデアは他のdivと同じように使えるはずです。 – sirion

関連する問題