3

オブジェクトのプロトタイプとして新しく作成された div を使用して、Javascript を介して DIV を「拡張」しようとしています。

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

別のオブジェクトを作成してDOMに追加するたびに、元のdivが「置換」されることを除いて、すべてが機能しているようです。より正確に言うと、コンストラクターは常に同じ div を変更します。

を使用MyTest.prototype = document.createElement("div");すると、説明した動作が得られます。コード例のその後にある 2 つのコメント行は、私も試しましたが、役に立ちませんでした。

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-Framework のため、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

ただし、最初の例の Div はコピーされていないようで、Singleton または Monostate のように動作します。このままではいけませんか?

  1. プロトタイプ オブジェクトは新しいオブジェクトにコピーされます
  2. 新しいオブジェクトは「this」に割り当てられます
  3. これはコンストラクタに渡されます
  4. これはコンストラクターによって返されます (return ステートメントが指定されていない場合)
4

3 に答える 3

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

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

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

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;
}

この関数は<div>、呼び出しを使用して新しい を作成しcreateElement()ます。次に、その new に必要なすべてのプロパティを設定します<div>。最後に、新しい を返します<div>。そのため、次のように呼び出すことができます

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

どちらのオプションも機能します。2 番目のケースでは、ダミーの新しいオブジェクトがキーワードによって作成されますが、関数内で作成された新しいオブジェクトが実際に返さnewれるため、問題ではありません。<div>

于 2012-04-10T15:34:58.403 に答える
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()を使用する逆の方法は機能しませんでした。

私の元々の問題はこれから来ました:プロトタイプがコピーされるとき、すべてのスカラー値がコピーされますが、すべてのオブジェクトは単純に参照されます(ポインターのコピーのように、ポインター値は複製されますが、それが指すデータは複製されません)。

これが誰かを助けることを願っています。

于 2012-04-11T14:26:04.023 に答える
0

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

document標準化された方法で に要素を追加することを計画しているようです。コードを次のように書き換えることができます (少し変更しました)。

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

documentこれを使用して、次のように `appendElement を使用して任意の要素を追加できます。

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

それはあなたが目指しているもののアイデアですか?

于 2012-04-10T16:23:14.793 に答える