Javascript如何实现单例模式呢?
1.非单例模式
我们先看以下的非单例模式。
module/video.js
class Video {
name = '';
constructor(name) {
this.name = name;
console.log(this.name + ',is constructed....')
}
}
Video.prototype.play = function(){
console.log(this.name+" is playing...")
}
test.js
import {Video} from './module/video.js'
const v1 = new Video('钢琴');
const v2 = new Video('小提琴');
console.log(v1===v2);
v1.play();
v2.play();
运行结果:
钢琴,is constructed....
小提琴,is constructed....
false
钢琴 is playing...
小提琴 is playing...
v1和v2显然是两个不同的对象,是非单例的。
2.传统方式实现单例。
module/singleton.js
export function singleton(className){
let ins;
return class {
constructor(...args) {
if(!ins){
ins = new className(...args);
}
return ins;
}
}
}
module/video.js
import {singleton} from "./singleton.js";
class Video {
name = '';
constructor(name) {
this.name = name;
console.log(this.name + ',is constructed....')
}
}
Video.prototype.play = function(){
console.log(this.name+" is playing...")
}
const videoInstance = singleton(Video);
export {videoInstance as Video};
test.js
import {Video} from './module/video.js'
const v1 = new Video('钢琴');
const v2 = new Video('小提琴');
console.log(v1===v2);
v1.play();
v2.play();
运行结果:
钢琴,is constructed....
true
钢琴 is playing...
钢琴 is playing...
这个结果看起来似乎一切正常。但是如果我们在创建完对象之后,无法在原型链上定义新方法,例如:
test.js
import {Video} from './module/video.js'
const v1 = new Video('钢琴');
const v2 = new Video('小提琴');
console.log(v1===v2);
v1.play();
v2.play();
Video.prototype.stop=function(){
console.log(this.name+" is stop playing....");
}
v1.stop();
v2.stop();
运行结果:
钢琴,is constructed....
true
钢琴 is playing...
钢琴 is playing...
file:///E:/node_project/test.js:19
v1.stop();
^
TypeError: v1.stop is not a function
3.使用代理实现单例
module/singleton.js
export function singleton(className){
let ins;
return new Proxy(className,{
construct(target, argArray, newTarget) {
if(!ins){
ins = new target(...argArray);
}
return ins;
}
})
}
module/video.js
import {singleton} from "./singleton.js";
class Video {
name = '';
constructor(name) {
this.name = name;
console.log(this.name + ',is constructed....')
}
}
Video.prototype.play = function(){
console.log(this.name+" is playing...")
}
const videoInstance = singleton(Video);
export {videoInstance as Video};
test.js
import {Video} from './module/video.js'
const v1 = new Video('钢琴');
const v2 = new Video('小提琴');
console.log(v1===v2);
v1.play();
v2.play();
Video.prototype.stop=function(){
console.log(this.name+" is stop playing....");
}
v1.stop();
v2.stop();
运行结果:
钢琴,is constructed....
true
钢琴 is playing...
钢琴 is playing...
钢琴 is stop playing....
钢琴 is stop playing....