我有一组 JavaScript“类”,其中基类定义了由继承类共享的函数.它正在工作,它是这样设置的:
var ThingA = function(name) {
    this.name = name;
};

ThingA.prototype = {
    sayHi: function() {
        alert('Hi,' + this.name + '!');
    }
};


var ThingB = function() {
    ThingA.call(this,'Charlie');
};

ThingB.prototype = new ThingA();
ThingB.prototype.constructor = ThingB;

var instanceOfB = new ThingB();
instanceOfB.sayHi();   // alerts 'Hi,Charlie!'

由于我无法控制的原因,我的公司更喜欢在编写JavaScript时遵循这种模式:

SomeClass = function() {

    // "Private" functions go here

    function somePrivateMethod() { 
        ...
    }

    return {

        // "Public" methods go here
        somePublicmethod: function() { ... }

    };
}();

现在,就事情而言,这是很好的,而且在很多情况下也是很好的.但它更是一种功能性的风格.只有一个“类”实例,一切都是静态的.

我被要求修改我的工作代码,更符合我公司喜欢的风格.所以我的问题是,有没有办法继承一个包装在工厂类中的类?它看起来像这样:

FactoryClassA = function() {

    var ThingA = function(name) {
        this.name = name;
    };

    ThingA.prototype = {
        sayHi: function() {
            alert('Hi,' + this.name + '!');
        }
    };

    return {
         createThingA: function(name) {
             return new ThingA(name);
         }
    };
}();


FactoryClassB = function() {

    // Define a ThingB class that inherits from ThingA somehow

    return {
         createThingB: function() {
             return new ThingB();
         }
    };
}();


var instanceOfB = FactoryClassB.createThingB();
instanceOfB.sayHi();   // should alert 'Hi,Charlie!'

有没有办法定义包含在FactoryClassB中的ThingB,它继承自FactoryClassA中包含的ThingA?感谢this question,我知道我不会这样做.我正在考虑使用一种方法来扩展给定的类…不知何故?

This answer似乎很接近,但是我无法弄清楚如何修改这个例子的细节,以适应我的情况.我愿意弯曲我公司的一般模式,但是我至少可以靠近它吗?

更新1

为了回应Adam的意见,只需要向工厂类添加一个参数,这里就是我被困住的地方:

ThingB.prototype = new ThingA();
ThingB.prototype.constructor = ThingB;

我不知道如何适应这些行,使其工作,如果我只是传入一个参数到工厂类方法.

解决方法

以下是我想要的(我相信)
FactoryClassA = function() {
    var ThingA = function(name) {
       this.name = name;
    };
    ThingA.prototype = {
        sayHi: function() {
            console.log('Hi,' + this.name + '!');
        }
    };
    // Add the constructor back to the prototype
    // (see explanation below)
    ThingA.prototype.constructor = ThingA;

    return {
        createThingA: function(name) {
            return new ThingA(name);
        }
    };
}();

FactoryClassB = function() {
    // Bootstrapping:
    // Capture the instance,as we'll need it to set up the prototype
    var baseInstance = new FactoryClassA.createThingA();
    // Capture the constructor
    var baseConstructor = baseInstance.constructor;
    // Keep a reference to the base prototype
    var baseProto = baseConstructor.prototype;

    function ThingB(name) {
        // Call base constructor,along with our args
        baseConstructor.call(this,name);
    };
    ThingB.prototype = baseInstance;
    ThingB.prototype.constructor = ThingB;

    ThingB.prototype.sayHi = function() {
        console.log('here I am');
        // call the base class `sayHi`
        baseProto.sayHi.call(this);
    };

    return {
        createThingB: function(name) {
            return new ThingB(name);
        }
    };
}();

// Testing
var foo = FactoryClassB.createThingB("Indeed");
foo.sayHi();

// Output:
//   here I am 
//   hi indeed

说明:

在FactoryClassA中,这一行是必要的:

ThingA.prototype.constructor = ThingA;

请注意,JS中的每个原型都将自动创建,并引用其构造函数.例如,当你做:

function T(){}

T.prototype已经有一个称为构造函数的属性,它返回到T.

但是,在ThingA的实现中,您可以通过执行ThingA.prototype = {…}重置整个原型.因此,您现在已经失去了对其构造函数的引用. 99%的病例是确定的,不会有任何负面的副作用(这可能是大多数开发者倾向于忘记它).然而,在继承的情况下,可能是必要的.

现在,在FactoryClassB中,我们需要做一些自举:

var baseInstance = new FactoryClassA.createThingA();
var baseConstructor = baseInstance.constructor;
var baseProto = baseConstructor.prototype;

观察最后两行,因为它们是在这种设计模式中实现继承的关键.首先,由于ThingA的构造函数可以通过原型(ThingA.prototype.constructor = ThingA)访问,那么这意味着给定ThingA的一个实例,我们可以直接检索其构造函数.由于构造函数是函数本身,并且由于每个函数都有对其原型的引用,所以我们可以使用baseConstructor.prototype来保存ThingA.prototype的引用.

接下来是关键部分,我们设置了继承链:

function ThingB(name) {
    // Call the base constructor
    baseConstructor.call(this,name);
};
ThingB.prototype = baseInstance;
ThingB.prototype.constructor = ThingB;

上面的最后一行是非常重要的,因为它告诉原型它的构造函数是什么,否则它仍然指向ThingA.

你有它 – 原型继承.

边注:

你可能会看到上述如何可以相当乏味,有点奇怪,重复. Ergo,你可能想考虑像Fiber.js这样的继承库,它遵循你想要的封装模式(以及一些奖金,如mixins和decorator).免责声明:我创作了图书馆.

如何在JavaScript中扩展一个闭包后面定义的类?的更多相关文章

  1. Xcode C开发,需要澄清

    我非常喜欢Xcode提供对该语言可能的成员函数的深入了解的方式,并且更喜欢相对于文本伙伴使用它,如果不是因为我今天注意到的奇怪.当strings=“Teststring”时;唯一可用的substr签名如图所示但据我所知,签名应该是什么iseeonline确实s.substr(1,2);既被理解也适用于Xcode.当我尝试方法完成时为什么不显示?

  2. xamarin.ios – 没有找到ViewController ::.ctor(System.IntPtr)的构造函数

    我有一个问题,我的Monotouch应用程序有时在收到内存警告后才会崩溃.请参见下面的堆栈跟踪.堆栈跟踪是正确的,因为指定的类缺少构造函数获取IntPtr参数.但是这是有意的,因为我在应用程序中根本不使用InterfaceBuilder.那为什么会这样呢?

  3. ios – Swift – NSURL错误

    尝试使用下面的NSURL类时出错,下面的代码实际上是试图将我从Facebook拉入的图像存储到imageView中.错误如下:不知道为什么会这样,帮忙!解决方法你正在调用的NSURL构造函数有这个签名:?表示构造函数可能不返回值,因此它被视为可选.NSData构造函数也是如此:快速解决方法是:最好的解决方案是检查(解包)这些选项,即使您确定它们包含值!

  4. 如何在Xcode中追踪“libc abi.dylib:纯虚函数!”

    我有一个多线程OSX应用程序,它使用C,Objective-C和Swift的混合.当我的应用程序关闭时,我在Xcode调试器窗口中看到了这一点:我知道这个错误通常是由对C类构造函数或析构函数中的虚函数的调用引起的.有没有一种简单的方法可以找到它的位置?

  5. Swift实现对象归档

    Swift实现对象归档时有几个注意点要继承NSCoding,实现两个方法extension是一个分类,分类不允许有存储能力,所以协议方法不能写在分类中协议中的init(coderdecoder:NSCoder)函数会覆盖原始的构造函数,所以类中至少还要有另一个init方法如果不指定键名,会使用属性名称作为key,基本数据类型,需要指定key

  6. 【Swift初见】Swift构造过程

    构造过程是通过构造器来实现的,其实每个构造器就可以看作是一个函数,只是这个函数是为了执行初始化的。每个类都必须拥有一个指定构造器。

  7. swift之ARC

    Swift使用自动引用计数来跟踪并管理应用使用的内存。大部分情况下,这意味着在Swift语言中,内存管理"仍然工作",不需要自己去考虑内存管理的事情。为了保证不会发生上述的情况,ARC跟踪与类的实例相关的属性、常量以及变量的数量。解决实例间的强引用环Swift提供两种方法来解决强引用环:弱引用和无主引用。在Swift语言中,推荐用可选类型来作为可能没有值的引用的类型。

  8. swift的struct结构体类型介绍使用

  9. Swift的函数与函数指针、闭包Closure等相关内容介绍

  10. swift struct

    //:Playground-noun:aplacewherepeoplecanplayimportCocoavarstr="Hello,playground"structpoint{varx=0;vary=init(x:Int,y:Int){self.x=x;y=y;println("init");}funcgetCenter()->Int{return(x+y)/2;}mutatingfunca

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部