3

我正在尝试通过使用新创建的 div 作为我的对象的原型来通过 Javascript“扩展”一个 DIV。

据我了解Javascript,在通过“new”创建我的对象的新实例时,原型对象被复制,分配给“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

然而,我的第一个示例中的 Div 似乎没有被复制,它的行为类似于 Singleton 或 Monostate。不应该这样吗?

  1. Protype 对象被复制到一个新对象中
  2. 新对象被分配给“this”
  3. 这是给构造函数的
  4. this 由构造函数返回(如果没有指定 return 语句)
4

3 回答 3

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

这一行只执行一次。它创建了一个MyTest.prototype对象,它也是一个 DOM 元素<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()。然后,它会在新的<div>. 最后,它返回您的新<div>. 因此,您可以将其称为

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

这两种选择都行得通。在第二种情况下,new关键字创建了一个虚拟的新对象,但这并不重要,因为<div>实际上返回了函数内部创建的新对象。

于 2012-04-10T15:34:58.403 回答
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);
}

现在您可以使用它来将任何元素附加到documentusing `appendElement ,如下所示:

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

这会是你的目标吗?

于 2012-04-10T16:23:14.793 回答
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 回答