Javascript 从HTML元素子类化(扩展)HTML元素?

Javascript 从HTML元素子类化(扩展)HTML元素?,javascript,html,dom,Javascript,Html,Dom,如果我能自己创建一个扩展HTML元素类的类,比如HTMLdevelment或HTMLImageElement,我会很高兴 假设采用标准继承模式: // class A: function ClassA(foo) { this.foo = foo; } ClassA.prototype.toString = function() { return "My foo is " + this.foo; }; // class B: function ClassB(foo, bar

如果我能自己创建一个扩展HTML元素类的类,比如HTMLdevelment或HTMLImageElement,我会很高兴

假设采用标准继承模式:

// class A:

function ClassA(foo) {
    this.foo = foo;
}

ClassA.prototype.toString = function() {
    return "My foo is " + this.foo;
};

// class B:

function ClassB(foo, bar) {
    ClassA.call(this, foo);
    this.bar = bar;
}

ClassB.prototype = new ClassA();

ClassB.prototype.toString = function() {
    return "My foo/bar is " + this.foo + "/" + this.bar;
};
我不知道在构造函数中调用什么:

function Image2() {
    // this doesn't work:
    Image2.prototype.constructor.call(this);
    // neither does this (only applies to <img>, no equivalent for <span> etc.):
    Image.call(this);
}

Image2.prototype = new Image(); // or document.createElement("img");

Image2.prototype.toString = function() {
    return "My src is " + this.src;
};
函数Image2(){
//这不起作用:
Image2.prototype.constructor.call(this);
//这也不适用(仅适用于

这是不可能的吗?还是有什么办法?谢谢。=)

这可能会对你有所帮助。在这个基于Javascript的游戏中,他扩展了DOM中的
元素

我相信他的技术是从他那里得来的

我不知道在构造函数中调用什么

Image2.prototype.constructor.call(this)

是的,JavaScript的对象没有像这样的类和可链接的构造函数。它有自己的原型模型,这可能会很混乱,但实际上并没有提供原型继承的适当潜力,因为它仍然绑定到构造函数函数,这些函数看起来像类构造函数,但实际上不是

不幸的是,这并不是真正创建子类;它只是伪装地扩展实例

是的-这就是JavaScript提供给你的所有内容。如果你愿意,你当然可以创建自己的对象系统,将其抽象出来,这样看起来就像是在创建类和实例。我在底部附上了一个我经常使用的示例。但在JavaScript中创建任何子类都没有标准

例如,在你的“标准”代码中,你说:

ClassA.call(this,foo)

但这只适用于编写ClassA的方式,因为您可以两次调用它,一次调用原型ClassA,将“foo”设置为“undefined”,然后再次调用从该原型继承的对象,将该“foo”隐藏在顶部另一个“foo”后面

这并不是类之间可能需要做的任何标准操作,当然也没有规定这将适用于非JS本机浏览器对象:

function MyImage() {
    Image.call(this); // might do anything. will almost certainly fail
}
MyImage.prototype= new Image();
在任何情况下,将原型设置为非本机JavaScript对象的HtmleElement都不是ECMAScript标准指定的,并且具有不同的成功程度;在IE中,它根本不起作用,原型的属性不起作用

而且

图2.prototype.constructor

从您的示例中可以看出,实际上可能与您预期的“Image”不同。“constructor”是一个非标准属性,在所有浏览器中都不可用,它在类系统中所做的事情与您所想的完全不同;最好避免

Image2应具有ImagePlus的所有属性/方法

目前,实现这一点的唯一方法是使用某种包装器。由于上述原因,您不能使用原型;您必须分别向每个实例添加属性:

function makeImage2() {
    var image= Image();
    image.isBig= function() {
        return this.width>200 || this.height>200;
    };
}
这当然只是一个工厂函数,而不是子类化。您必须为instanceof提供自己的替换


不,你不能。(至少在今天的浏览器中,从IE6到IE6都不可靠;我不知道在尖端浏览器中,这种情况最近是否发生了变化。)

David发布的链接提供了一个涉及工厂方法的解决方案。它不是通过任何方式继承的,但它提供了一种方便的方法来生成用所需属性和方法装饰的DOM元素实例。您可以链接装饰器调用以“构建”专用实例

工厂方法(不必使用Object.defineProperty):

使用中:

var el = newElement();
el.myVar = "Boo!";
el.saySomething(); // alerts "Boo!"
document.body.appendChild(el); // A div with text "Boo!" is added to the body

好的,这个问题需要更新当前的技术

HTML5为您提供了创建自定义元素的方法。您需要通过
document.registerement
注册您的元素,然后您可以像使用任何其他标记一样使用它。该功能已在最新的Chrome中提供。我不确定是否有其他浏览器

详情如下:


Javascripts原型继承与我们OO迷习惯的任何继承都有很大的不同。理想的结果是什么?:它与您习惯的继承是一样的(在任何可以使用Image的地方,您都应该能够插入Image2,Image2应该拥有Image的所有属性/方法以及更多);它只是用Javascript写的不同而已。这样,而且这种风格没有私有/受保护的属性/方法。这个答案有用吗?@kangax很抱歉这么晚才回复,但不幸的是没有。我的意思是“扩展”如“subclass from”中的“extend”;那张海报要求“extend”如“将方法添加到原型”中的“extend”。谢谢,但不幸的是,这并不是真正创建子类;它只是伪装地扩展实例。我最大的缺点是(x instanceof Image2)不会返回true,并且不能使用构造函数(new Image2)。更主观的是,它还修改了一个内置函数,这是一个黑客行为,但我不认为有太多!投票通过了,但我想更新IE9+似乎支持使用HTML元素的原型的未来读者。
// Create a custom div with a setter and a method.
function newElement(){
    // Create an element to decorate.
    var el = document.createElement('div');
    // A "private" variable.
    var _myVar = null;
    // Create a setter
    Object.defineProperty(el, "myVar", {
        set : function(value){
            _myVar = value;
            this.innerHTML = value;
        }
    });
    // Create a method
    Object.defineProperty(el, "saySomething", {
        value : function(){
            alert(_myVar);
        }
    });
    return el;
}
var el = newElement();
el.myVar = "Boo!";
el.saySomething(); // alerts "Boo!"
document.body.appendChild(el); // A div with text "Boo!" is added to the body