Javascript 将 Singleton JS 对象转换为使用 ES6 类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26205565/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:31:17  来源:igfitidea点击:

Converting Singleton JS objects to use ES6 classes

javascriptecmascript-6ecmascript-harmony

提问by justingordon

I'm using ES6 with the Webpack es6-transpiler per my article here: http://www.railsonmaui.com/blog/2014/10/02/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/

根据我的文章,我将 ES6 与 Webpack es6-transpiler 一起使用:http://www.railsonmaui.com/blog/2014/10/02/integrating-webpack-and-the-es6-transpiler-into-an-现有轨道项目/

Does it make any sense to convert two Singleton objects to use ES6 Classes?

将两个 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 };

This is file ManagerProducts.jsx that has a singleton that should extend from 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 };

回答by Jason Sebring

No. Makes no sense.

不。没有意义。

Here's a really simple example of a singleton object in es6:

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

let appState = {};
export default appState;

If you really want to use a class in your singleton approach, I would recommend against using "static" as it more confusing than good for a singleton at least for JS and instead return the instance of the class as a singleton like so...

如果你真的想在你的单例方法中使用一个类,我建议不要使用“静态”,因为它至少对于 JS 来说对于单例来说更令人困惑而不是好,而是将类的实例作为单例返回,就像这样......

class SomeClassUsedOnlyAsASingleton {
  // implementation
}

export default new SomeClassUsedOnlyAsASingleton();

This way you can still use all the class things you like that JavaScript offers but it will reduce the confusion as IMO static isn't fully supported in JavaScript classes anyway as it is in typed languages such as c# or Java as it only supports static methods unless you just fake it and attach them directly to a class (at the time of this writing).

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

回答by Brian Genisio

I'd argue that singletons (classes that manage their own singleton lifetime) are unnecessary in any language. That is not to say that singleton lifetime is not useful, just that I prefer that something other than the class manage the lifetime of an object, like a DI container.

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

That being said, the singleton pattern CAN be applied to JavaScript classes, borrowing the "SingletonEnforcer" pattern that was used in ActionScript. I can see wanting to do something like this when porting an existing code base that uses singletons into ES6.

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

In this case, the idea is that you make a private (via an un exposed Symbol) static singletoninstance, with a public static instancegetter. You then restrict the constructor to something that has access to a special singletonEnforcersymbol that is not exposed outside of the module. That way, the constructor fails if anyone other than the singleton tries to "new" it up. It would look something like this:

在这种情况下,想法是singleton使用公共静态instancegetter创建一个私有(通过未公开的 Symbol)静态实例。然后将构造函数限制为可以访问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

Then you can use it like any other singleton:

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

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

回答by AdrianD

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

我必须做同样的事情,所以这里有一个简单而直接的方法来做一个单身人士,屈膝礼在 es6 中的单身人士类

(original link http://amanvirk.me/singleton-classes-in-es6/)

(原文链接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.logcalls should print the same cache.time(Singleton)

两个console.log调用都应该打印相同的cache.time(单例)

回答by Milan Karunarathne

In order to create Singleton patternuse a single instance with ES6 classes;

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

'use strict';

import EventEmitter from 'events';

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

    getState() {
        return this.state;
    }

}

export default let single = new Single();

Update: According to @Bergi explanation, below one is not a valid argument.

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

This works because of (refer to Steven)

这是因为(参考Steven

> If I understand CommonJS + the browser implementations correctly, the > output of a module is cached, so export default new MyClass() will > result in something that behaves as a singleton (only a single > instance of this class will ever exist per process/client depending on > env it's running in). > 如果我正确理解 CommonJS + 浏览器实现,模块的 > 输出会被缓存,因此导出默认的 new MyClass() 将 > 导致某些行为类似于单例(每个类的单个 > 实例将永远存在)进程/客户端取决于> env 它正在运行)。

You can find an example here ES6 Singleton.

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

Note: This pattern is using in Flux Dispacher

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

Flux: www.npmjs.com/package/flux

通量:www.npmjs.com/package/flux

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

调度程序示例github.com/facebook/flux/blob/master/examples/flux-todomvc/js/dispatcher/AppDispatcher.js#L16

回答by M. Hamza Rajput

Singleton class

单例类

class SingletonClass {
    constructor( name = "", age = 0 ) {
        if ( !this.constructor.instance ) {

            this.constructor.instance = this;
            this.name = name;
            this.age = age;

        }

        return this.constructor.instance;
    }

    getName() {
        return this.name;
    }

    getAge() {
        return this.age;
    }
}
    
const instanceOne = new SingletonClass( "One", 25 );
const instanceTwo = new SingletonClass( "Two", 44 );

console.log( `Name of instanceOne is "${instanceOne.getName()}"` );
console.log( `Name of instanceTwo is "${instanceTwo.getName()}"` );