Javascript ES6 单例 vs 一次实例化一个类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/48366563/
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
ES6 Singleton vs Instantiating a Class once
提问by Aaron
I see patterns which make use of a singleton pattern using ES6 classes and I am wondering why I would use them as opposed to just instantiating the class at the bottom of the file and exporting the instance. Is there some kind of negative drawback to doing this? For example:
我看到使用 ES6 类使用单例模式的模式,我想知道为什么要使用它们,而不是仅在文件底部实例化类并导出实例。这样做有什么负面的缺点吗?例如:
ES6 Exporting Instance:
ES6 导出实例:
import Constants from '../constants';
class _API {
constructor() {
this.url = Constants.API_URL;
}
getCities() {
return fetch(this.url, { method: 'get' })
.then(response => response.json());
}
}
const API = new _API();
export default API;
Usage:
用法:
import API from './services/api-service'
What is the difference from using the following Singleton pattern? Are there any reasons for using one from the other? Im actually more curious to know if the first example I gave can have issues that I am not aware of.
与使用以下单例模式有什么区别?是否有任何理由使用另一个?我实际上更想知道我给出的第一个例子是否有我不知道的问题。
Singleton Pattern:
单例模式:
import Constants from '../constants';
let instance = null;
class API {
constructor() {
if(!instance){
instance = this;
}
this.url = Constants.API_URL;
return instance;
}
getCities() {
return fetch(this.url, { method: 'get' })
.then(response => response.json());
}
}
export default API;
Usage:
用法:
import API from './services/api-service';
let api = new API()
采纳答案by Zlatko
The difference is if you want to test things.
不同之处在于您是否想测试事物。
Say you have api.spec.jstest file. And that your API thingy has one dependency, like those Constants.
假设你有api.spec.js测试文件。并且您的 API 有一个依赖项,例如那些常量。
Specifically, constructor in both your versions takes one parameter, your Constantsimport.
具体来说,您的两个版本中的构造函数都采用一个参数,即您的Constants导入。
So your constructor looks like this:
所以你的构造函数看起来像这样:
class API {
constructor(constants) {
this.API_URL = constants.API_URL;
}
...
}
// single-instance method first
import API from './api';
describe('Single Instance', () => {
it('should take Constants as parameter', () => {
const mockConstants = {
API_URL: "fake_url"
}
const api = new API(mockConstants); // all good, you provided mock here.
});
});
Now, with exporting instance, there's no mocking.
现在,通过导出实例,没有嘲笑。
import API from './api';
describe('Singleton', () => {
it('should let us mock the constants somehow', () => {
const mockConstants = {
API_URL: "fake_url"
}
// erm... now what?
});
});
With instantiated object exported, you can't (easily and sanely) change its behavior.
导出实例化对象后,您无法(轻松且明智地)更改其行为。
回答by Bergi
I would recommend neither. This is totally overcomplicated. If you only need one object, do not use the classsyntax! Just go for
我都不推荐。这完全过于复杂了。如果您只需要一个对象,请不要使用class语法!就去吧
import Constants from '../constants';
export default {
url: Constants.API_URL,
getCities() {
return fetch(this.url, { method: 'get' }).then(response => response.json());
}
};
import API from './services/api-service'
or even simpler
或者更简单
import Constants from '../constants';
export const url = Constants.API_URL;
export function getCities() {
return fetch(url, { method: 'get' }).then(response => response.json());
}
import * as API from './services/api-service'
回答by Peter
Another reason to use Singleton Pattern is in some frameworks (like Polymer 1.0) you can't use exportsyntax.
That's why second option (Singleton pattern) is more useful, for me.
使用单例模式的另一个原因是在某些框架(如Polymer 1.0)中不能使用export语法。
这就是为什么第二个选项(单例模式)对我来说更有用。
Hope it helps.
希望能帮助到你。
回答by Sumer
Both are different ways. Exporting a class like as below
两者都是不同的方式。导出如下所示的类
const APIobj = new _API();
export default APIobj; //shortcut=> export new _API()
and then importing like as below in multiple files would point to same instance and a way of creating Singleton pattern.
然后在多个文件中像下面这样导入将指向相同的实例和创建单例模式的方法。
import APIobj from './services/api-service'
Whereas the other way of exporting the class directly is not singleton as in the file where we are importing we need to new up the class and this will create a separate instance for each newing up Exporting class only:
而另一种直接导出类的方式不是单例,因为在我们导入的文件中,我们需要新建类,这将为每个新建的导出类创建一个单独的实例:
export default API;
Importing class and newing up
导入类并更新
import API from './services/api-service';
let api = new API()
回答by UtkarshPramodGupta
In addition to all the answers given, a classhas the property of getting extended (inheritance). How possibly do you think you can let developers extend your class, if all you are exporting is a single instancefrom its module file?
除了给出的所有答案之外,aclass还具有扩展(继承)的属性。class如果您导出的只是模块文件中的单个实例,您认为您有多大可能让开发人员扩展您的.

