转换辛格尔顿JS对象使用ES6类

问题描述:

我使用ES6每个我的文章的WebPack ES6-transpiler这里:http://www.railsonmaui.com/blog/2014/10/02/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/转换辛格尔顿JS对象使用ES6类

这有什么意义转换2单一对象使用ES6类?

import { CHANGE_EVENT } from "../constants/Constants"; 

var EventEmitter = require('events').EventEmitter; 
var merge = require('react/lib/merge'); 

var _flash = null; 

var BaseStore = merge(EventEmitter.prototype, { 

    emitChange: function() { 
    this.emit(CHANGE_EVENT); 
    }, 

    /** 
    * @param {function} callback 
    */ 
    addChangeListener: function(callback) { 
    this.on(CHANGE_EVENT, callback); 
    }, 

    /** 
    * @param {function} callback 
    */ 
    removeChangeListener: function(callback) { 
    this.removeListener(CHANGE_EVENT, callback); 
    }, 

    getFlash: function() { 
    return _flash; 
    }, 

    setFlash: function(flash) { 
    _flash = flash; 
    } 
}); 

export { BaseStore }; 

这是文件ManagerProducts.jsx,它有一个应该从BaseStore扩展的单例。

/** 
* Client side store of the manager_product resource 
*/ 
import { BaseStore } from "./BaseStore"; 
import { AppDispatcher } from '../dispatcher/AppDispatcher'; 
import { ActionTypes } from '../constants/Constants'; 
import { WebAPIUtils } from '../utils/WebAPIUtils'; 
import { Util } from "../utils/Util"; 
var merge = require('react/lib/merge'); 

var _managerProducts = []; 

var receiveAllDataError = function(action) { 
    console.log("receiveAllDataError %j", action); 
    WebAPIUtils.logAjaxError(action.xhr, action.status, action.err); 
}; 

var ManagerProductStore = merge(BaseStore, { 
    getAll: function() { 
    return _managerProducts; 
    } 
}); 

var receiveAllDataSuccess = function(action) { 
    _managerProducts = action.data.managerProducts; 
    //ManagerProductStore.setFlash({ message: "Manager Product data loaded"}); 
}; 


ManagerProductStore.dispatchToken = AppDispatcher.register(function(payload) { 
    var action = payload.action; 
    if (Util.blank(action.type)) { throw `Invalid action, payload ${JSON.stringify(payload)}`; } 

    switch(action.type) { 
    case ActionTypes.RECEIVE_ALL_DATA_SUCCESS: 
     receiveAllDataSuccess(action); 
     break; 
    case ActionTypes.RECEIVE_ALL_DATA_ERROR: 
     receiveAllDataError(action); 
     break; 
    default: 
     return true; 
    } 
    ManagerProductStore.emitChange(); 
    return true; 
}); 

export { ManagerProductStore }; 
+2

号如果你有一个单身,你不需要在JavaScript中的一类。类用于构造多个实例。 – Bergi 2014-10-05 18:06:32

+0

@bergi,这就是我的想法。但只是检查是否有什么我失踪。 – justingordon 2014-10-05 22:09:59

我认为单身人士(管理他们自己的单身人士生命的班级)在任何语言中都是不必要的。这并不是说singleton的生命周期没有用处,只是我更喜欢除了班级以外的其他东西来管理对象的生命周期,例如DI容器。

也就是说,singleton模式可以应用于JavaScript类,借用ActionScript中使用的“SingletonEnforcer”模式。在将现有的使用单例的代码移植到ES6中时,我可以看到想要做类似这样的事情。

在这种情况下,您的想法是您可以通过一个公共静态instance getter来创建一个私有(通过一个未公开的Symbol)的静态singleton实例。然后,将构造函数限制为可以访问不在模块外部暴露的特殊singletonEnforcer符号的内容。这样,如果单身人士以外的任何人尝试“新”起来,构造函数就会失败。这将是这个样子:

const singleton = Symbol(); 
const singletonEnforcer = Symbol() 

class SingletonTest { 

    constructor(enforcer) { 
    if(enforcer != singletonEnforcer) throw "Cannot construct singleton"; 
    } 

    static get instance() { 
    if(!this[singleton]) { 
     this[singleton] = new SingletonTest(singletonEnforcer); 
    } 
    return this[singleton]; 
    } 
} 

export default SingletonTest 

然后你可以使用它像任何其他单:

import SingletonTest from 'singleton-test'; 
const instance = SingletonTest.instance; 
+12

http://amanvirk.me/singleton-classes-in-es6/是更好的方法,因为它在构造函数本身内部管理状态 – 2015-05-20 09:45:46

+0

@AmanVirk如果您要扩展该类,该方法是否可行? – 2015-09-03 17:54:08

+1

IMO在实例获取器中使用这个有点奇怪。 它不能引用类本身,因为它是一种静态方法。 我宁愿把 ''' const instance = null; ''' 以外的类,然后在代码中使用实例。无论如何,处理器将把所有这些都放在关闭中,所以最终它将成为一个私有变量。 除此之外,它似乎是一个很好的解决方案! – dejakob 2016-02-06 16:12:49

号是没有意义的。

这里有一个单一对象的ES6一个非常简单的例子:

let appState = {}; 
export default appState; 

如果你真的想在你的单身的方法来使用一个类,我会建议不要使用“静态”,因为它多好困惑对于一个单身至少JS,而是返回类像这样一个单独的实例...

class SomeClassUsedOnlyAsASingleton { 
    // implementation 
} 

export default new SomeClassUsedOnlyAsASingleton(); 

这样你仍然可以使用所有类的东西,你喜欢JavaScript的报价,但会降低混乱,因为IMO静态不完全支持在JavaScript类中,因为它是类似于c#或Java的语言,因为它只支持静态方法,除非你直接伪造它并将它们直接附加到一个类(在撰写本文时)。

+3

或者只是一行'export default let appState = {};':-) – Bergi 2015-04-30 21:57:03

+0

@Jason:谢谢,你真的睁开了眼睛。我也尝试过定义一个单例类,但有一个单一的对象要简单得多。正如你甚至可以在这个对象中定义函数一样,我完全看不出任何缺点。 – waldgeist 2015-08-21 09:27:49

+0

let appState = { func:function(){ //等等等等 } }; – pyrsmk 2015-09-29 06:44:39

为了创建Singleton模式使用带有ES6类的单个实例;

'use strict'; 

import EventEmitter from 'events'; 

class Single extends EventEmitter { 
    constructor() { 
     this.state = {}; 
    } 

    getState() { 
     return this.state; 
    } 

} 

export default let single = new Single(); 

更新:根据@Bergi解释,下面一个是不是一个有效的参数。

这工作,因为(参考Steven

>如果我理解正确CommonJS的+浏览器实现中, >模块的输出缓存,所以出口默认新MyClass的()将 >导致某行为表现为单例行为(根据运行的环境,只有一个 >这个类的实例将永远存在于每个进程/客户端)。

你可以在这里找到一个例子ES6 Singleton

:该图案在助焊剂Dispacher

助焊剂使用:www.npmjs.com/package/flux

Dispacher例github.com/facebook/flux/ blob/master/examples/flux-todomvc/js/dispatcher/AppDispatcher.js#L16

+0

不要这样做!当你不想要一个类时,不应该使用'class'语法!即使这种模式在Flux中使用,它也不一定是一个好模式。顺便说一句,那个引用是错误的,使用'new singleton.constructor'创建第二个实例是微不足道的。 – Bergi 2015-11-12 22:56:06

+0

@Bergi让我们假设Dispatcher是一个类实现,我想扩展它的功能。所以,我使用JS ES6'extends'创建了另一个名为AppDispacher的类,并且需要该类的单个实例。那我必须使用[这种方法](http://*.com/a/26227662/4640228)?但** Jason **说“没有意义”。那么,你的方法是什么?我不明白一件事。你让这个答案错了​​。但它在Facebook这样的公司工作和使用。 :) – 2015-11-13 12:11:57

+0

那么,如果你在你的应用程序中使用多个调度程序,这可能是有意义的,但即使你有只导出单个实例的模块,我也不会称之为“单例”。 – Bergi 2015-11-13 12:20:24

我必须这样做,所以这里是一个简单而直接的做单身的方法, 屈膝礼来http://amanvirk.me/singleton-classes-in-es6/

let instance = null; 

class Cache{ 
    constructor() { 
     if(!instance){ 
       instance = this; 
     } 

     // to test whether we have singleton or not 
     this.time = new Date() 

     return instance; 
     } 
} 


let cache = new Cache() 
console.log(cache.time); 

setTimeout(function(){ 
    let cache = new Cache(); 
    console.log(cache.time); 
},4000); 

两个console.log电话应打印相同cache.time(辛格尔顿)

+2

不适用于扩展类。 – shinzou 2017-04-25 10:41:12

+0

@shinzou是什么让你觉得它不适用于扩展类?所有的子类都会返回相同的单例实例,这就是单例的工作原理。 – Bergi 2017-12-23 19:44:11