- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我通过 C++、Java 等语言熟悉 OOP 概念。现在我正在尝试将 JavaScript 作为一种爱好来学习,主要是出于对 WebGL 的兴趣。但是我在基于原型(prototype)的继承方面遇到了麻烦。
假设我有一个基类,它在构造函数中接受一个参数。我需要扩展它。我这样做的方式如下所示。
function Base(n) {
this._n = n;
}
Base.prototype.print = function() {
console.log(this._n);
}
function Derived(n) {
Base.call(this, n);
}
Derived.prototype = new Base;
Derived.prototype.constructor = Derived;
现在这是我的理解:单个 Base
对象用作 Derived
的原型(prototype)。所以 Derived
的所有实例都将从这个 Base
对象继承属性,例如print
方法。当我调用 new Derived(10)
然后创建一个新对象时,函数 Derived
在这个新创建的对象的上下文中被调用,即 this
指向新创建的对象,从函数 Derived
调用函数 Base
,然后创建 _n
并赋值 10。所以如果我创建了 5 个 Derived
对象,它们都有自己的 _n
属性。到目前为止一切正常。
但我不喜欢这一行:
Derived.prototype = new Base;
Function Base
需要一个参数,但我在这里没有传递任何内容。此处没有必要传递参数,因为此对象将充当 Derived
的原型(prototype)。而且我不需要此原型(prototype)对象的任何 _n
值。但是如果函数 Base
依赖于参数呢?比方说,Base
加载资源并将路径作为参数传递。那怎么办?
总而言之,我的问题是:
_n
)? Derived.prototype = new Base;
正在创建一个 Base
的实例,它将始终保留在内存中(假设 Derived
定义在全局空间)。如果 Base
类非常昂贵并且我不想要额外的对象怎么办? 最佳答案
首先,非常感谢您对 JavaScript 的原型(prototype)继承的理解如此透彻。你显然已经完成了功课。大多数具有 Java 或 C++ 背景的人往往都非常挣扎,但您已经度过了最糟糕的时期。
Function
Base
expects an argument but I am passing nothing here. What to do with data members in prototype object (_n
in this example)?
如果需要使用Base
作为基类,则需要将其设计为合理地接受零参数,或者需要在为Derived<创建基类对象时带参调用它
。这些基本上是您仅有的两个选择。
Derived.prototype = new Base;
is creating an instance ofBase
and this will remain in memory always (assumingDerived
is defined in global space). What to do ifBase
class is very costly and I don't want an extra object?
它与 Java 类中的 static
数据相同:加载类会加载该数据。如果您要使用 Base
作为基础,您需要对其进行设计,使其不会加载一堆不需要的东西(也许通过以不同于有参数版本的方式处理零参数版本)。
这是您通常在 JavaScript 的“类”系统中看到的最后一种方法(处理零参数构造与有参数构造不同)。通常你会看到实际的构造函数只用于构造一个原始对象,以及一些其他用于实际初始化实例的命名函数(initialize
是 Prototype 使用的名称,我在执行 my replacement/revision of Prototype's mechanism 时使用的名称) .所以实际的构造函数不带任何参数,但随后您将通过调用 initialize
函数(它又调用其基础的 initialize
函数)来初始化一个实例。在大多数包装器中,这些都是在幕后为您处理的。
要使构造函数与初始化器机制在实践中发挥作用,需要一些棘手的管道,因为它需要“ super 调用”(调用函数的基版本),而 super 调用在 JavaScript 中很笨拙。 ( super 调用实际上是链接文章的主要内容,但探索一种有效的方法也涉及创建/更新整个继承系统。我真的需要更新那篇文章,这样它就不会不要使用基于类的术语;它仍然是原型(prototype),它只是提供了我正在谈论的管道。)
因为外部资源可能会消失/移动/等等,而且 Stack Overflow 基本上是独立的,所以这是 the article linked above 中呈现的迭代的最终结果:
// Take IV: Explicitly handle mixins, provide a mixin for calling super when
// working with anonymous functions.
// Inspired by Prototype's Class class (http://prototypejs.org)
// Copyright (C) 2009-2010 by T.J. Crowder
// Licensed under the Creative Commons Attribution License 2.0 (UK)
// http://creativecommons.org/licenses/by/2.0/uk/
var Helper = (function(){
var toStringProblematic, // true if 'toString' may be missing from for..in
valueOfProblematic; // true if 'valueOf' may be missing from for..in
// IE doesn't enumerate toString or valueOf; detect that (once) and
// remember so makeClass can deal with it. We do this with an anonymous
// function we don't keep a reference to to minimize what we keep
// around when we're done.
(function(){
var name;
toStringProblematic = valueOfProblematic = true;
for (name in {toString: true, valueOf: true}) {
if (name == 'toString') {
toStringProblematic = false;
}
if (name == 'valueOf') {
valueOfProblematic = false;
}
}
})();
// This function is used to create the prototype object for our generated
// constructors if the class has a parent class. See makeConstructor for details.
function protoCtor() { }
// Build and return a constructor; we do this with a separate function
// to minimize what the new constructor (a closure) closes over.
function makeConstructor(base) {
// Here's our basic constructor function (each class gets its own, a
// new one of these is created every time makeConstructor is called).
function ctor() {
// Call the initialize method
this.initialize.apply(this, arguments);
}
// If there's a base class, hook it up. We go indirectly through `protoCtor`
// rather than simply doing "new base()" because calling `base` will call the base
// class's `initialize` function, which we don't want to execute. We just want the
// prototype.
if (base) {
protoCtor.prototype = base.prototype;
ctor.prototype = new protoCtor();
protoCtor.prototype = {}; // Don't leave a dangling reference
}
// Set the prototype's constructor property so `this.constructor` resolves
// correctly
ctor.prototype.constructor = ctor;
// Flag up that this is a constructor (for mixin support)
ctor._isConstructor = true;
// Return the newly-constructed constructor
return ctor;
}
// This function is used when a class doesn't have its own initialize
// function; since it does nothing and can only appear on base classes,
// all instances can share it.
function defaultInitialize() {
}
// Get the names in a specification object, allowing for toString and
// valueOf issues
function getNames(members) {
var names, // The names of the properties in 'members'
name, // Each name
nameIndex; // Index into 'names'
names = [];
nameIndex = 0;
for (name in members) {
names[nameIndex++] = name;
}
if (toStringProblematic && typeof members.toString != 'undefined') {
names[nameIndex++] = 'toString';
}
if (valueOfProblematic && typeof members.valueOf != 'undefined') {
names[nameIndex++] = 'valueOf';
}
return names;
}
// makeClass: Our public "make a class" function.
// Arguments:
// - base: An optional constructor for the base class.
// - ...: One or more specification objects containing properties to
// put on our class as members; or functions that return
// specification objects. If a property is defined by more than one
// specification object, the last in the list wins.
// Returns:
// A constructor function for instances of the class.
//
// Typical use will be just one specification object, but allow for more
// in case the author is drawing members from multiple locations.
function makeClass() {
var base, // Our base class (constructor function), if any
argsIndex, // Index of first unused argument in 'arguments'
ctor, // The constructor function we create and return
members, // Each members specification object
names, // The names of the properties in 'members'
nameIndex, // Index into 'names'
name, // Each name in 'names'
value, // The value for each name
baseValue; // The base class's value for the name
// We use this index to keep track of the arguments we've consumed
argsIndex = 0;
// Do we have a base?
if (typeof arguments[argsIndex] == 'function' &&
arguments[argsIndex]._isConstructor) {
// Yes
base = arguments[argsIndex++];
}
// Get our constructor; this will hook up the base class's prototype
// if there's a base class, and mark the new constructor as a constructor
ctor = makeConstructor(base);
// Assign the members from the specification object(s) to the prototype
// Again, typically there's only spec object, but allow for more
while (argsIndex < arguments.length) {
// Get this specification object
members = arguments[argsIndex++];
if (typeof members == 'function') {
members = members();
}
// Get all of its names
names = getNames(members);
// Copy the members
for (nameIndex = names.length - 1; nameIndex >= 0; --nameIndex) {
name = names[nameIndex];
value = members[name];
if (base && typeof value == 'function' && !value._isMixinFunction) {
baseValue = base.prototype[name];
if (typeof baseValue == 'function') {
value.$super = baseValue;
}
}
ctor.prototype[name] = value;
}
}
// If there's no initialize function, provide one
if (!('initialize' in ctor.prototype)) {
// Note that this can only happen in base classes; in a derived
// class, the check above will find the base class's version if the
// subclass didn't define one.
ctor.prototype.initialize = defaultInitialize;
}
// Return the constructor
return ctor;
}
// makeMixin: Our public "make a mixin" function.
// Arguments:
// - ...: One or more specification objects containing properties to
// put on our class as members; or functions that return
// specification objects. If a property is defined by more than one
// specification object, the last in the list wins.
// Returns:
// A specification object containing all of the members, flagged as
// mixin members.
function makeMixin() {
var rv, // Our return value
argsIndex, // Index of first unused argument in 'arguments'
members, // Each members specification object
names, // The names in each 'members'
value; // Each value as we copy it
// Set up our return object
rv = {};
// Loop through the args (usually just one, but...)
argsIndex = 0;
while (argsIndex < arguments.length) {
// Get this members specification object
members = arguments[argsIndex++];
if (typeof members == 'function') {
members = members();
}
// Get its names
names = getNames(members);
// Copy its members, marking them as we go
for (nameIndex = names.length - 1; nameIndex >= 0; --nameIndex) {
name = names[nameIndex];
value = members[name];
if (typeof value == 'function') {
value._isMixinFunction = true;
}
rv[name] = value;
}
}
// Return the consolidated, marked specification object
return rv;
}
// Return our public members
return {
makeClass: makeClass,
makeMixin: makeMixin
};
})();
用法:
var Parent = Helper.makeClass(function(){
function hierarchy() {
return "P";
}
return {hierarchy: hierarchy};
});
var Child = Helper.makeClass(Parent, function(){
function hierarchy() {
return hierarchy.$super.call(this) + " < C";
}
return {hierarchy: hierarchy};
});
var GrandChild = Helper.makeClass(Child, function(){
function hierarchy() {
return hierarchy.$super.call(this) + " < GC";
}
return {hierarchy: hierarchy};
});
var gc = new GrandChild();
alert(gc.hierarchy()); // Alerts "P < C < GC"
如果您不喜欢 supercalls 的 funcname.$super.call(...)
符号,这里有一个 mix-in 可以让您使用更短/更清晰的版本(但在运行时成本):
// Define our CallSuper mixin
Helper.CallSuperMixin = makeMixin(function() {
function callSuper(ref) {
var f, // The function to call
args, // Arguments to pass it, if we have any
len, // Length of args to pass
srcIndex, // When copying, the index into 'arguments'
destIndex, // When copying args, the index into 'args'
rv; // Our return value
// Get the function to call: If they pass in a function, it's the
// subclass's version so look on $super; otherwise, they've passed
// in 'arguments' and it's on arguments.callee.$super.
f = typeof ref == 'function' ? ref.$super : ref.callee.$super;
// Only proceed if we have 'f'
if (f) {
// If there are no args to pass on, use Function#call
if (arguments.length == 1) {
rv = f.call(this);
} else {
// We have args to pass on, build them up.
// Note that doing this ourselves is more efficient on most
// implementations than applying Array.prototype.slice to
// 'arguments', even though it's built in; the call to it
// is expensive (dramatically, on some platforms).
len = arguments.length - 1;
args = new Array(len);
srcIndex = 1;
destIndex = 0;
while (destIndex < len) {
args[destIndex++] = arguments[srcIndex++];
}
// Use Function#apply
rv = f.apply(this, args);
}
}
// Done
return rv; // Will be undefined if there was no 'f' to call
}
return {callSuper: callSuper};
});
再一次,我真的需要更新术语,这样它就不是基于类的了。 (并且可能会看看 ECMAScript5 如何让我们做一些稍微不同的事情,因为它添加了一些有用的东西,比如对原型(prototype)的直接控制。)
关于javascript - JS : Confusion about inheritance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7944880/
我正在为我的项目测试 FlowJS,我遇到了 Type Aliases 的问题. 我为 API 构建了一个 Web SDK:我有一个使用此方法的 Helper 类: class Helper {
我是 Dart 的新手,仍在学习它带来的所有细微差别。我当前的任务真正困扰的一件事是从父类继承(或代理)静态方法。 void main() { EnglishCasual.greet(); } c
我正在尝试巩固 Go 提供的继承概念(也许是“组合”而不是纯粹的继承)。但是,我无法理解为什么我不能将“父”类型用作 func 参数来生成作用于该参数的通用函数。 package main impor
我在准确表述它时遇到问题,所以我在标题中留下了更笼统的描述(如果您对问题有更准确的描述,请发表评论,我会编辑标题)。 问题: AudioStream 和VideoStream 两个类派生自基类Medi
我的应用程序不仅具有“用户”,而且还具有“管理员”和“ super 管理员”。由于所有这三个共享相同的属性,因此我只想使用一个带有附加属性“role”的表,该属性可以是“user”,“admin”或“
我正在使用数据库优先方法和 DbContext。我的数据模型中有几个继承结构 (TPH)。但是 DbContext 只为基类创建一个 DbSet,而没有为子类创建一个 DbSet。我应该如何检索指定子
我正在使用数据库优先方法和 DbContext。我的数据模型中有几个继承结构 (TPH)。但是 DbContext 只为基类创建一个 DbSet,而没有为子类创建一个 DbSet。我应该如何检索指定子
我有一个生成很多子对象的应用程序,每个子对象都与一些全局应用程序对象一起工作,例如在全局应用程序注册表中注册自己,更新应用程序统计信息等。 应用程序应该如何将访问这些全局对象的能力传递给 child
我有 2 个结构,其中一个继承了由 type Common struct {...} 表示的所有结构中共有的值 type Common struct{ Id int CreatedAt
我的代码: Ext.onReady(function() { // Every property is declared inside the class Ext.define('MyCustomPa
我有一个包含多个类的应用程序,这些类继承/是第三方库类的子类。例如,来自 Qt Framework 的 QDialog。 我应该在应用程序的 UML 类图中指定继承关系吗? 是否期望(或标准)表示此类
我遇到了这个问题,因为我认为我对 Backbone 的理解不正确。 我有一个名为 Runnable 的父类(super class)和一组继承自它的子类: var Runnable = Backbon
考虑以下 HTML: foo bar 和 CSS: a { text-decoration:none; border-bottom-width: 0px; border-bot
我想做个模板Class BaseDialog ,但在进行最终对话时 MyDialog1 , 继承了 BaseDialog , 我收到错误,然后无法在设计模式下显示对话框。 以下是我得到的错误列表。 a
我对 android 文档中的这两个术语感到困惑!! these screenshot about what i mean 最佳答案 常量是用 static 和 final 修饰符声明的字段。继承常量
我最近遇到了一个新的警告: 继承构造函数不继承省略号 我正在尝试管道 Object{42}; // ... into an init that handles integers ...和... Obj
我正在使用 TypeScript 开发 Aurelia 应用程序。在此应用程序中,我定义了一组自定义元素,每个元素共享一组可绑定(bind)属性,这些属性被转换为 css 设置,如以下简化示例所示:
我想知道为什么人们会说: “继承类不继承构造函数”。 如果你可以使用父类的构造函数,无参构造函数无论如何都会被自动调用。 例子: #include using namespace std; clas
我刚刚开始探索 Kotlin 语言。我正在为继承、var&val 和副作用而苦苦挣扎。 如果我用 val x 声明一个特征 A 并在 AImpl 中覆盖 x ,则可以将其覆盖为 var(参见下面的代码
我正面临一个编码/解码问题,涉及使用 MOXy 的 JAXB 实现和外部元数据绑定(bind)文件的继承和多态性。 我无法控制 XML 文件或模型类。 模型内部有多个类继承其他 DTO 类。 这是我正
我是一名优秀的程序员,十分优秀!