如果我可以创建自己的扩展HTML元素类的类,我会喜欢它,例如HTMLDivElement或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;
};
这是不可能的吗?还是有某种方法?谢谢。 =)
答案 0 :(得分:4)
好的,这个问题需要更新当前的技术。
HTML5提供了创建自定义元素的方法。您需要通过document.registerElement
注册您的元素,之后您可以像使用任何其他标签一样使用它。该功能已在最新的Chrome中提供。我不确定其他浏览器。
此处有更多详情:
http://www.html5rocks.com/en/tutorials/webcomponents/customelements/
答案 1 :(得分:3)
我无法弄清楚构造函数中要调用的内容
Image2.prototype.constructor.call(本);
是的,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();
在任何情况下,ECMAScript标准都没有指定原型设置为非本机JavaScript对象的HTMLElement,并且具有不同程度的成功;在IE中它根本不起作用,原型的属性不需要。
此外,
您的示例中的Image2.prototype.constructor
实际上可能与您期望的“图像”不同。 “构造函数”除了是一个在所有浏览器中都不可用的非标准属性之外,还会在类系统中做出一些根本不是你想到的东西;最好避免。
Image2应具有Image plus的所有属性/方法
目前,唯一的方法是使用某种包装器。由于上述原因,您无法使用原型执行此操作;你必须分别为每个实例添加属性:
function makeImage2() {
var image= Image();
image.isBig= function() {
return this.width>200 || this.height>200;
};
}
这当然只是一个工厂功能,而不是像子类化那样的东西。您必须为instanceof提供自己的替代品。
...
// An example class system
//
Function.prototype.subclass= function() {
var c= new Function(
'if (!(this instanceof arguments.callee)) throw(\'Constructor called without "new"\'); '+
'if (arguments[0]!==Function.prototype.subclass._FLAG && this._init) this._init.apply(this, arguments); '
);
if (this!==Object)
c.prototype= new this(Function.prototype.subclass._FLAG);
return c;
};
Function.prototype.subclass._FLAG= {};
// Usage
//
ClassA= Object.subclass();
ClassA.prototype._init= function(foo) {
this.foo= foo;
};
ClassA.prototype.toString= function() {
return 'My foo is '+this.foo;
};
ClassB= ClassA.subclass();
ClassB.prototype._init= function(foo, bar) {
ClassA.prototype._init.call(this, foo);
this.bar= bar;
};
ClassB.prototype.toString= function() {
return ClassA.prototype.toString.call(this)+' and my bar is '+this.bar;
};
答案 2 :(得分:2)
这可能会对你有所帮助。在这个基于Javascript的游戏中,他扩展了DOM中的table
个元素。 MiniRacer on CodeProject
我相信他从this article by Paul Sowden得到了他的技巧。
答案 3 :(得分:1)
不,你不能。 (至少在今天的浏览器和IE6之间不可靠;我不知道最近的浏览器情况是否最近发生了变化。)
答案 4 :(得分:1)
David发布的链接提供了一个涉及工厂方法的解决方案。它不是任何方式的继承,但它提供了一种方便的方法来生成用您想要的属性和方法修饰的DOM元素的实例。您可以将装饰器调用链接到“构建”专用实例。
工厂方法(您不必使用Object.defineProperty):
// 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