ES6单例对一次实例化类

我看到一些模式使用 ES6类的单例模式,我想知道为什么我要使用它们,而不是仅仅在文件底部实例化类并导出实例。这么做有什么不好的地方吗?例如:

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;

用法:

import API from './services/api-service'

使用下列单例模式有何分别?有什么理由使用其中一个吗?实际上我更好奇的是,我给出的第一个例子是否有我没有意识到的问题。

单例模式

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;

用法:

import API from './services/api-service';


let api = new API()
58692 次浏览

The difference is if you want to test things.

Say you have api.spec.js test file. And that your API thingy has one dependency, like those Constants.

Specifically, constructor in both your versions takes one parameter, your Constants import.

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.

I would recommend neither. This is totally overcomplicated. If you only need one object, do not use the class syntax! Just go for

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'

Another reason to use Singleton Pattern is in some frameworks (like Polymer 1.0) you can't use export syntax.
That's why second option (Singleton pattern) is more useful, for me.

Hope it helps.

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()

Maybe I'm late, because this question is written in 2018, but it still appear in the top of result page when search for js singleton class and I think that it still not have the right answer even if the others ways works. but don't create a class instance. And this is my way to create a JS singleton class:

class TestClass {
static getInstance(dev = true) {
if (!TestClass.instance) {
console.log('Creating new instance');
Object.defineProperty(TestClass, 'instance', {
value: new TestClass(dev),
writable : false,
enumerable : true,
configurable : false
});
} else {
console.log('Instance already exist');
}
return TestClass.instance;
}
random;
constructor() {
this.random = Math.floor(Math.random() * 99999);
}
}
const instance1 = TestClass.getInstance();
console.log(`The value of random var of instance1 is: ${instance1.random}`);
const instance2 = TestClass.getInstance();
console.log(`The value of random var of instance2 is: ${instance2.random}`);

And this is the result of execution of this code.

Creating new instance
The value of random var of instance1 is: 14929
Instance already exist
The value of random var of instance2 is: 14929

Hope this can help someone