转换Singleton JS对象以使用ES6类

时间:2014-10-05 17:58:31

标签: javascript ecmascript-6 ecmascript-harmony

我在我的文章中使用ES6和Webpack es6-transpiler:http://www.railsonmaui.com/blog/2014/10/02/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/

将两个Singleton对象转换为使用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 };

5 个答案:

答案 0 :(得分:67)

否。毫无意义。

这是es6中单例对象的一个​​非常简单的例子:

let appState = {};
export default appState;

如果您真的想在单身方法中使用课程,我建议不要使用"静态"至少对于一个单身人士来说,至少对于JS而言更令人困惑,而是将类的实例作为单身人士返回,就像这样......

class SomeClassUsedOnlyAsASingleton {
  // implementation
}

export default new SomeClassUsedOnlyAsASingleton();

通过这种方式,您仍然可以使用JavaScript提供的所有类别的东西,但它可以减少混淆,因为在JavaScript类中完全不支持IMO静态,因为它在类型语言(如c#或Java)中是它只支持静态方法,除非你伪造它并将它们直接附加到类(在撰写本文时)。

答案 1 :(得分:38)

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

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

在这种情况下,我们的想法是使用公共静态singleton getter创建一个私有(通过未公开的符号)静态instance实例。然后,您可以将构造函数限制为可以访问未在模块外部公开的特殊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;

答案 2 :(得分:11)

I had to do the same so here is a simple and direct way of doing a singleton, curtsy to singleton-classes-in-es6

(original link 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);

Both console.log calls should print the same cache.time (Singleton)

答案 3 :(得分:5)

为了创建单例模式,使用带有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

<德尔> &GT;如果我正确理解CommonJS +浏览器实现,那么 &GT;模块的输出被缓存,因此导出默认的新MyClass()将 &GT;导致表现为单身的东西(只有一个单身 &GT;每个进程/客户端将依赖于此类的实例 &GT; env它正在运行)。

您可以在ES6 Singleton找到示例。

注意:此模式在Flux Dispacher中使用

Flux :www.npmjs.com/package/flux

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

答案 4 :(得分:0)

单人班

c.changeGlyph = function(id){
        c.right = !c.right
    }