Cách đơn giản nhất / sạch nhất để triển khai mẫu singleton trong JavaScript là gì?
Cách đơn giản nhất / sạch nhất để triển khai mẫu singleton trong JavaScript là gì?
Câu trả lời:
Tôi nghĩ cách dễ nhất là khai báo một đối tượng đơn giản theo nghĩa đen:
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
Nếu bạn muốn các thành viên riêng trên cá thể đơn lẻ của mình, bạn có thể làm một cái gì đó như thế này:
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// all private members are accessible here
},
publicMethod2: function () {
}
};
})();
Điều này đã được gọi là các kiểu mô-đun , nó về cơ bản cho phép bạn đóng gói các thành viên tin về một đối tượng, bằng cách tận dụng việc sử dụng đóng cửa .
CẬP NHẬT: Tôi muốn thêm rằng nếu bạn muốn ngăn chặn việc sửa đổi đối tượng singleton, bạn có thể đóng băng nó , sử dụng Object.freeze
phương thức ES5 .
Điều đó sẽ làm cho đối tượng bất biến, ngăn chặn mọi sửa đổi đối với cấu trúc và giá trị của nó.
Ngoài ra, tôi muốn đề cập rằng nếu bạn đang sử dụng ES6, bạn có thể biểu diễn một singleton bằng Mô-đun ES rất dễ dàng và thậm chí bạn có thể giữ trạng thái riêng tư bằng cách khai báo các biến ở phạm vi mô-đun :
// my-singleton.js
const somePrivateState = []
function privateFn () {
// ...
}
export default {
method1() {
// ...
},
method2() {
// ...
}
}
Sau đó, bạn có thể chỉ cần nhập đối tượng singleton để sử dụng nó:
import myInstance from './my-singleton.js'
// ...
publicMethod1
gọi publicMethod2
?
getInstance
phương thức tĩnh và một hàm tạo riêng - nhưng IMO, đây là cách "đơn giản" nhất để xây dựng một đối tượng singleton trong Javascript và cuối cùng, nó đáp ứng cùng một mục đích - một đối tượng duy nhất, mà bạn không thể khởi tạo lại (không có hàm tạo, nó chỉ là một đối tượng) -. Về mã bạn đã liên kết, nó có một số vấn đề, trao đổi a
và b
khai báo biến và kiểm tra a === window
. Chúc mừng.
Tôi nghĩ rằng cách tiếp cận sạch nhất là một cái gì đó như:
var SingletonFactory = (function(){
function SingletonClass() {
//do stuff
}
var instance;
return {
getInstance: function(){
if (instance == null) {
instance = new SingletonClass();
// Hide the constructor so the returned object can't be new'd...
instance.constructor = null;
}
return instance;
}
};
})();
Sau đó, bạn có thể gọi hàm như
var test = SingletonFactory.getInstance();
delete instance.constructor
:x = SingletonClass.getInstance();delete x.constructor;new x.constructor;
Tôi không chắc chắn tôi đồng ý với mẫu mô-đun được sử dụng để thay thế cho mẫu đơn. Tôi thường thấy các singleton được sử dụng và lạm dụng ở những nơi hoàn toàn không cần thiết và tôi chắc chắn rằng mô-đun sẽ lấp đầy nhiều khoảng trống trong đó các lập trình viên sẽ sử dụng một singleton, tuy nhiên mô hình mô-đun không phải là một singleton.
var foo = (function () {
"use strict";
function aPrivateFunction() {}
return { aPublicFunction: function () {...}, ... };
}());
Mọi thứ khởi tạo trong mô hình mô đun xảy ra khi Foo
được khai báo. Ngoài ra, mẫu mô-đun có thể được sử dụng để khởi tạo một hàm tạo, sau đó có thể được khởi tạo nhiều lần. Mặc dù mẫu mô-đun là công cụ phù hợp cho nhiều công việc, nhưng nó không tương đương với một mẫu đơn.
var Foo = function () {
"use strict";
if (Foo._instance) {
//this allows the constructor to be called multiple times
//and refer to the same instance. Another option is to
//throw an error.
return Foo._instance;
}
Foo._instance = this;
//Foo initialization code
};
Foo.getInstance = function () {
"use strict";
return Foo._instance || new Foo();
}
hình thức dài, sử dụng mô hình mô-đun
var Foo = (function () {
"use strict";
var instance; //prevent modification of "instance" variable
function Singleton() {
if (instance) {
return instance;
}
instance = this;
//Singleton initialization code
}
//instance accessor
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
Trong cả hai phiên bản của mẫu Singleton mà tôi đã cung cấp, chính hàm tạo có thể được sử dụng làm trình truy cập:
var a,
b;
a = new Foo(); //constructor initialization happens here
b = new Foo();
console.log(a === b); //true
Nếu bạn không cảm thấy thoải mái khi sử dụng hàm tạo theo cách này, bạn có thể đưa ra lỗi trong if (instance)
câu lệnh và sử dụng biểu mẫu dài:
var a,
b;
a = Foo.getInstance(); //constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); //true
Tôi cũng nên đề cập rằng mẫu singleton rất phù hợp với mẫu hàm xây dựng ẩn:
function Foo() {
if (Foo._instance) {
return Foo._instance;
}
//if the function wasn't called as a constructor,
//call it as a constructor and return the result
if (!(this instanceof Foo)) {
return new Foo();
}
Foo._instance = this;
}
var f = new Foo(); //calls Foo as a constructor
-or-
var f = Foo(); //also calls Foo as a constructor
var singleton = {}
không phù hợp với định nghĩa đó.
var singleton = {}
là cách bạn triển khai singleton trong Javascript .
Trong es6
:
class Singleton {
constructor () {
if (!Singleton.instance) {
Singleton.instance = this
}
// Initialize object
return Singleton.instance
}
// Properties & Methods
}
const instance = new Singleton()
Object.freeze(instance)
export default instance
instance
trường. Vì hiện tại ( instance
được đặt thành this
) lớp này cũng có thể có các trường khác và việc đóng băng không có nghĩa là imo.
Các hoạt động sau đây trong nút v6
class Foo {
constructor(msg) {
if (Foo.singleton) {
return Foo.singleton;
}
this.msg = msg;
Foo.singleton = this;
return Foo.singleton;
}
}
Chúng tôi kiểm tra:
const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }
Trong ES6, cách đúng đắn để làm điều này là:
class MyClass {
constructor() {
if (MyClass._instance) {
throw new Error("Singleton classes can't be instantiated more than once.")
}
MyClass._instance = this;
// ... your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass() // Executes succesfully
var instanceTwo = new MyClass() // Throws error
Hoặc, nếu bạn không muốn ném lỗi khi tạo phiên bản thứ hai, bạn có thể trả về phiên bản cuối cùng, như sau:
class MyClass {
constructor() {
if (MyClass._instance) {
return MyClass._instance
}
MyClass._instance = this;
// ... your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass()
var instanceTwo = new MyClass()
console.log(instanceOne === instanceTwo) // logs "true"
instance
và _instance
. Nó chỉ là một quy ước đặt tên trong các ngôn ngữ lập trình mà chúng tôi đặt tên cho các biến riêng được đặt trước một dấu gạch dưới. Tôi nghi ngờ lý do khiến mã của bạn không hoạt động là vì bạn đang sử dụng this.instance
thay vìMyClass.instance
Có nhiều hơn một cách để nuôi mèo :) Tùy theo sở thích hoặc nhu cầu cụ thể của bạn, bạn có thể áp dụng bất kỳ giải pháp được đề xuất nào. Cá nhân tôi đi tìm giải pháp đầu tiên của CMS bất cứ khi nào có thể (khi bạn không cần sự riêng tư). Vì câu hỏi là đơn giản và sạch sẽ nhất, đó là người chiến thắng. Hoặc thậm chí:
var myInstance = {}; // done!
Điều này (trích dẫn từ blog của tôi) ...
var SingletonClass = new function() {
this.myFunction() {
//do stuff
}
this.instance = 1;
}
không có ý nghĩa gì nhiều (ví dụ blog của tôi cũng không có) bởi vì nó không cần bất kỳ lọ riêng tư nào, vì vậy nó khá giống với:
var SingletonClass = {
myFunction: function () {
//do stuff
},
instance: 1
}
this.f(){}
Tôi không tán thành câu trả lời của mình, xem cái khác của tôi .
Thông thường mẫu mô-đun (xem câu trả lời của CMS) KHÔNG phải mẫu đơn là đủ tốt. Tuy nhiên, một trong những tính năng của singleton là việc khởi tạo của nó bị trì hoãn cho đến khi cần đối tượng. Mô hình mô-đun thiếu tính năng này.
Đề xuất của tôi (CoffeeScript):
window.singleton = (initializer) ->
instance = undefined
() ->
return instance unless instance is undefined
instance = initializer()
Được biên dịch thành cái này trong JavaScript:
window.singleton = function(initializer) {
var instance;
instance = void 0;
return function() {
if (instance !== void 0) {
return instance;
}
return instance = initializer();
};
};
Sau đó tôi có thể làm như sau:
window.iAmSingleton = singleton(function() {
/* This function should create and initialize singleton. */
alert("creating");
return {property1: 'value1', property2: 'value2'};
});
alert(window.iAmSingleton().property2); // "creating" will pop up; then "value2" will pop up
alert(window.iAmSingleton().property2); // "value2" will pop up but "creating" will not
window.iAmSingleton().property2 = 'new value';
alert(window.iAmSingleton().property2); // "new value" will pop up
Vì bản chất không chặn của JavaScript, Singletons trong JavaScript thực sự xấu khi sử dụng. Các biến toàn cục sẽ cung cấp cho bạn một phiên bản thông qua toàn bộ ứng dụng mà không cần tất cả các cuộc gọi lại này, mô-đun mô-đun nhẹ nhàng ẩn bên trong giao diện. Xem câu trả lời @CMS.
Nhưng, vì bạn muốn có một singleton
var singleton = function(initializer) {
var state = 'initial';
var instance;
var queue = [];
var instanceReady = function(createdInstance) {
state = 'ready';
instance = createdInstance;
while (callback = queue.shift()) {
callback(instance);
}
};
return function(callback) {
if (state === 'initial') {
state = 'waiting';
queue.push(callback);
initializer(instanceReady);
} else if (state === 'waiting') {
queue.push(callback);
} else {
callback(instance);
}
};
};
Sử dụng:
var singletonInitializer = function(instanceReady) {
var preparedObject = {property: 'value'};
// calling instanceReady notifies singleton that instance is ready to use
instanceReady(preparedObject);
}
var s = singleton(singletonInitializer);
// get instance and use it
s(function(instance) {
instance.doSomething();
});
Singletons cung cấp cho bạn nhiều hơn chỉ một trường hợp thông qua toàn bộ ứng dụng: việc khởi tạo của chúng bị trì hoãn cho đến lần sử dụng đầu tiên. Đây thực sự là một điều lớn khi bạn đối phó với các đối tượng có khởi tạo đắt tiền. Đắt tiền thường có nghĩa là I / O và trong JavaScript I / O luôn có nghĩa là gọi lại.
Đừng tin tưởng câu trả lời cung cấp cho bạn giao diện như thế nào instance = singleton.getInstance()
, tất cả đều bỏ lỡ điểm.
Nếu họ không thực hiện cuộc gọi lại để chạy khi cá thể đã sẵn sàng, thì họ sẽ không hoạt động khi trình khởi tạo thực hiện I / O.
Vâng, các cuộc gọi lại luôn trông xấu hơn so với chức năng gọi ngay lập tức trả về thể hiện đối tượng. Nhưng một lần nữa: khi bạn thực hiện I / O, các cuộc gọi lại là bắt buộc. Nếu bạn không muốn thực hiện bất kỳ I / O nào, thì khởi tạo đủ rẻ để thực hiện khi bắt đầu chương trình.
var simpleInitializer = function(instanceReady) {
console.log("Initializer started");
instanceReady({property: "initial value"});
}
var simple = singleton(simpleInitializer);
console.log("Tests started. Singleton instance should not be initalized yet.");
simple(function(inst) {
console.log("Access 1");
console.log("Current property value: " + inst.property);
console.log("Let's reassign this property");
inst.property = "new value";
});
simple(function(inst) {
console.log("Access 2");
console.log("Current property value: " + inst.property);
});
Trong ví dụ này setTimeout
giả mạo một số hoạt động I / O đắt tiền. Điều này minh họa tại sao singletons trong JavaScript thực sự cần gọi lại.
var heavyInitializer = function(instanceReady) {
console.log("Initializer started");
var onTimeout = function() {
console.log("Initializer did his heavy work");
instanceReady({property: "initial value"});
};
setTimeout(onTimeout, 500);
};
var heavy = singleton(heavyInitializer);
console.log("In this example we will be trying");
console.log("to access singleton twice before it finishes initialization.");
heavy(function(inst) {
console.log("Access 1");
console.log("Current property value: " + inst.property);
console.log("Let's reassign this property");
inst.property = "new value";
});
heavy(function(inst) {
console.log("Access 2. You can see callbacks order is preserved.");
console.log("Current property value: " + inst.property);
});
console.log("We made it to the end of the file. Instance is not ready yet.");
Tôi đã lấy ví dụ này từ các mẫu JavaScript Xây dựng các ứng dụng tốt hơn với mã hóa và thiết kế mẫu của cuốn sách của Stoyan Stefanov trong trường hợp bạn cần một số lớp triển khai đơn giản như đối tượng singl tone, bạn có thể sử dụng chức năng ngay lập tức như sau:
var ClassName;
(function() {
var instance;
ClassName = function ClassName() {
//If private instance variable already initialized return reference
if(instance) {
return instance;
}
//If instance does not created save pointer of original reference
//to private instance variable.
instance = this;
//All constructor initialization will be here
// i.e.:
this.someProperty = 0;
this.someMethod = function() {
//Some action here
};
};
}());
Và bạn có thể kiểm tra ví dụ này bằng cách kiểm tra trường hợp sau:
//Extending defined class like Singltone object using new prototype property
ClassName.prototype.nothing = true;
var obj_1 = new ClassName();
//Extending defined class like Singltone object using new prototype property
ClassName.prototype.everything = true;
var obj_2 = new ClassName();
//Testing does this two object pointing to same instance
console.log(obj_1 === obj_2); //Result is true, it points to same instance object
//All prototype properites work
//no matter when they were defined
console.log(obj_1.nothing && obj_1.everything
&& obj_2.nothing && obj_2.everything); //Result true
//Values of properties which is defined inside of constructor
console.log(obj_1.someProperty);// output 0
console.log(obj_2.someProperty);// output 0
//Changing property value
obj_1.someProperty = 1;
console.log(obj_1.someProperty);// output 1
console.log(obj_2.someProperty);// output 1
console.log(obj_1.constructor === ClassName); //Output true
Cách tiếp cận này vượt qua tất cả các trường hợp thử nghiệm trong khi triển khai tĩnh riêng sẽ thất bại khi sử dụng phần mở rộng nguyên mẫu (có thể sửa nhưng không đơn giản) và triển khai tĩnh công khai ít được khuyến khích hơn do cá thể được phơi bày ra công chúng.
Tôi nghĩ rằng tôi đã tìm thấy cách lập trình sạch nhất trong JavaScript, nhưng bạn sẽ cần một chút trí tưởng tượng. Tôi có ý tưởng này từ một kỹ thuật làm việc trong cuốn sách "javascript các phần tốt".
Thay vì sử dụng từ khóa mới, bạn có thể tạo một lớp như thế này:
function Class()
{
var obj = {}; // Could also be used for inheritence if you don't start with an empty object.
var privateVar;
obj.publicVar;
obj.publicMethod= publicMethod;
function publicMethod(){}
function privateMethod(){}
return obj;
}
Bạn có thể khởi tạo đối tượng trên bằng cách nói:
var objInst = Class(); // !!! NO NEW KEYWORD
Bây giờ với phương pháp làm việc này, bạn có thể tạo một singleton như thế này:
ClassSingleton = function()
{
var instance= null;
function Class() // This is the class like the above one
{
var obj = {};
return obj;
}
function getInstance()
{
if( !instance )
instance = Class(); // Again no new keyword;
return instance;
}
return { getInstance : getInstance };
}();
Bây giờ bạn có thể lấy ví dụ của bạn bằng cách gọi
var obj = ClassSingleton.getInstance();
Tôi nghĩ rằng đây là cách gọn gàng nhất vì "Lớp" hoàn chỉnh thậm chí không thể truy cập được.
@CMS và @zzzzBov đều đã đưa ra những câu trả lời tuyệt vời, nhưng chỉ để thêm cách giải thích của riêng tôi dựa trên việc tôi đã chuyển sang phát triển node.js nặng từ PHP / Zend Framework trong đó các mẫu singleton là phổ biến.
Các mã tài liệu nhận xét sau đây dựa trên các yêu cầu sau:
Mã của tôi rất giống với @ zzzzBov, ngoại trừ tôi đã thêm một chuỗi nguyên mẫu vào hàm tạo và nhiều nhận xét sẽ giúp những người đến từ PHP hoặc một ngôn ngữ tương tự dịch OOP truyền thống sang bản chất nguyên mẫu của Javascripts. Nó có thể không phải là "đơn giản nhất" nhưng tôi tin rằng nó là đúng đắn nhất.
// declare 'Singleton' as the returned value of a self-executing anonymous function
var Singleton = (function () {
"use strict";
// 'instance' and 'constructor' should not be availble in a "public" scope
// here they are "private", thus available only within
// the scope of the self-executing anonymous function
var _instance=null;
var _constructor = function (name) {
this.name = name || 'default';
}
// prototypes will be "public" methods available from the instance
_constructor.prototype.getName = function () {
return this.name;
}
// using the module pattern, return a static object
// which essentially is a list of "public static" methods
return {
// because getInstance is defined within the same scope
// it can access the "private" 'instance' and 'constructor' vars
getInstance:function (name) {
if (!_instance) {
console.log('creating'); // this should only happen once
_instance = new _constructor(name);
}
console.log('returning');
return _instance;
}
}
})(); // self execute
// ensure 'instance' and 'constructor' are unavailable
// outside the scope in which they were defined
// thus making them "private" and not "public"
console.log(typeof _instance); // undefined
console.log(typeof _constructor); // undefined
// assign instance to two different variables
var a = Singleton.getInstance('first');
var b = Singleton.getInstance('second'); // passing a name here does nothing because the single instance was already instantiated
// ensure 'a' and 'b' are truly equal
console.log(a === b); // true
console.log(a.getName()); // "first"
console.log(b.getName()); // also returns "first" because it's the same instance as 'a'
Lưu ý rằng về mặt kỹ thuật, chức năng ẩn danh tự thực hiện chính nó là một Singleton như được thể hiện độc đáo trong mã được cung cấp bởi @CMS. Điều hấp dẫn duy nhất ở đây là không thể sửa đổi chuỗi nguyên mẫu của hàm tạo khi bản thân hàm tạo là ẩn danh.
Hãy nhớ rằng với Javascript, các khái niệm về công khai và các trò chơi riêng tư không được áp dụng như PHP hay Java. Nhưng chúng tôi đã đạt được hiệu quả tương tự bằng cách tận dụng các quy tắc về tính khả dụng của phạm vi chức năng của Javascript.
var a = Singleton.getInstance('foo'); var b = new a.constructor('bar');
Không chắc chắn tại sao không ai đưa ra điều này, nhưng bạn chỉ có thể làm:
var singleton = new (function() {
var bar = 123
this.foo = function() {
// whatever
}
})()
Câu trả lời rõ ràng nhất phải là câu hỏi này từ cuốn sách Học các mẫu thiết kế JavaScript của Addy Osmani.
var mySingleton = (function () {
// Instance stores a reference to the Singleton
var instance;
function init() {
// Singleton
// Private methods and variables
function privateMethod(){
console.log( "I am private" );
}
var privateVariable = "Im also private";
var privateRandomNumber = Math.random();
return {
// Public methods and variables
publicMethod: function () {
console.log( "The public can see me!" );
},
publicProperty: "I am also public",
getRandomNumber: function() {
return privateRandomNumber;
}
};
};
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if ( !instance ) {
instance = init();
}
return instance;
}
};
})();
Tôi tin rằng đây là cách đơn giản nhất / sạch nhất và trực quan nhất mặc dù nó yêu cầu ES7:
export default class Singleton { static instance; constructor(){ if(instance){ return instance; } this.state = "duke"; this.instance = this; } }
Mã nguồn là từ: adam-bien.com
new Singleton()
Tôi có thể đặt 5 đồng tiền của tôi. Tôi có một hàm xây dựng, ví dụ.
var A = function(arg1){
this.arg1 = arg1
};
Điều tôi cần làm chỉ là mọi đối tượng được tạo bởi CF này sẽ giống nhau.
var X = function(){
var instance = {};
return function(){ return instance; }
}();
kiểm tra
var x1 = new X();
var x2 = new X();
console.log(x1 === x2)
Tôi đã tìm thấy sau đây là mẫu Singleton dễ nhất, bởi vì sử dụng toán tử mới làm cho điều này ngay lập tức có sẵn trong hàm, loại bỏ nhu cầu trả về một đối tượng theo nghĩa đen:
var singleton = new (function () {
var private = "A private value";
this.printSomething = function() {
console.log(private);
}
})();
singleton.printSomething();
Dưới đây là ví dụ đơn giản để giải thích mẫu singleton trong javascript.
var Singleton=(function(){
var instance;
var init=function(){
return {
display:function(){
alert("This is a Singleton patern demo");
}
};
};
return {
getInstance:function(){
if(!instance){
alert("Singleton check");
instance=init();
}
return instance;
}
};
})();
// In this call first display alert("Singleton check")
// and then alert("This is a Singleton patern demo");
// It means one object is created
var inst=Singleton.getInstance();
inst.display();
// In this call only display alert("This is a Singleton patern demo")
// it means second time new object is not created,
// it uses the already created object
var inst1=Singleton.getInstance();
inst1.display();
Tôi cần một vài singletons với:
và đây là những gì tôi nghĩ ra:
createSingleton ('a', 'add', [1, 2]);
console.log(a);
function createSingleton (name, construct, args) {
window[name] = {};
window[construct].apply(window[name], args);
window[construct] = null;
}
function add (a, b) {
this.a = a;
this.b = b;
this.sum = a + b;
}
args phải là Array để điều này hoạt động, vì vậy nếu bạn có các biến trống, chỉ cần chuyển vào []
Tôi đã sử dụng đối tượng cửa sổ trong hàm nhưng tôi có thể đã truyền vào một tham số để tạo phạm vi của riêng mình
Các tham số tên và cấu trúc chỉ là Chuỗi cho cửa sổ [] để hoạt động nhưng với một số cách kiểm tra kiểu đơn giản, window.name và window.construct cũng có thể.
Làm thế nào về cách này, chỉ cần đảm bảo lớp không thể mới một lần nữa.
Bằng cách này, bạn có thể sử dụng instanceof
op, đồng thời, bạn có thể sử dụng chuỗi nguyên mẫu để kế thừa lớp, đó là một lớp thông thường, nhưng không thể mới, nếu bạn muốn lấy cá thể chỉ cần sử dụnggetInstance
function CA()
{
if(CA.instance)
{
throw new Error('can not new this class');
}else{
CA.instance = this;
}
}
/**
* @protected
* @static
* @type {CA}
*/
CA.instance = null;
/** @static */
CA.getInstance = function()
{
return CA.instance;
}
CA.prototype =
/** @lends CA#*/
{
func: function(){console.log('the func');}
}
// initilize the instance
new CA();
// test here
var c = CA.getInstance()
c.func();
console.assert(c instanceof CA)
// this will failed
var b = new CA();
Nếu bạn không muốn để lộ instance
thành viên, chỉ cần đóng nó lại.
sau đây là đoạn trích từ bước đi của tôi để thực hiện một mô hình đơn lẻ. Điều này xảy ra với tôi trong quá trình phỏng vấn và tôi cảm thấy rằng tôi nên nắm bắt điều này ở đâu đó.
/*************************************************
* SINGLETON PATTERN IMPLEMENTATION *
*************************************************/
//since there are no classes in javascript, every object is technically a singleton
//if you don't inherit from it or copy from it.
var single = {};
//Singleton Implementations
//Declaring as a Global Object...you are being judged!
var Logger = function() {
//global_log is/will be defined in GLOBAL scope here
if(typeof global_log === 'undefined'){
global_log = this;
}
return global_log;
};
//the below 'fix' solves the GLOABL variable problem but
//the log_instance is publicly available and thus can be
//tampered with.
function Logger() {
if(typeof Logger.log_instance === 'undefined'){
Logger.log_instance = this;
}
return Logger.log_instance;
};
//the correct way to do it to give it a closure!
function logFactory() {
var log_instance; //private instance
var _initLog = function() { //private init method
log_instance = 'initialized';
console.log("logger initialized!")
}
return {
getLog : function(){ //the 'privileged' method
if(typeof log_instance === 'undefined'){
_initLog();
}
return log_instance;
}
};
}
/***** TEST CODE ************************************************
//using the Logger singleton
var logger = logFactory();//did i just gave LogFactory a closure?
//create an instance of the logger
var a = logger.getLog();
//do some work
//get another instance of the logger
var b = logger.getLog();
//check if the two logger instances are same?
console.log(a === b); //true
*******************************************************************/
cùng có thể được tìm thấy trên của tôi ý chính trang
function Unicode()
{
var i = 0, unicode = {}, zero_padding = "0000", max = 9999;
//Loop through code points
while (i < max) {
//Convert decimal to hex value, find the character, then pad zeroes to the codepoint
unicode[String.fromCharCode(parseInt(i, 16))] = ("u" + zero_padding + i).substr(-4);
i = i + 1;
}
//Replace this function with the resulting lookup table
Unicode = unicode;
}
//Usage
Unicode();
//Lookup
Unicode["%"]; //returns 0025
Bạn có thể làm điều đó với các trình trang trí như trong ví dụ dưới đây cho TypeScript:
class YourClass {
@Singleton static singleton() {}
}
function Singleton(target, name, descriptor) {
var instance;
descriptor.value = () => {
if(!instance) instance = new target;
return instance;
};
}
Sau đó, bạn sử dụng singleton của bạn như thế này:
var myInstance = YourClass.singleton();
Theo văn bản này, các trình trang trí không có sẵn trong các công cụ JavaScript. Bạn sẽ cần đảm bảo thời gian chạy JavaScript của bạn có các trình trang trí thực sự được kích hoạt hoặc sử dụng các trình biên dịch như Babel và TypeScript.
Cũng lưu ý rằng cá thể singleton được tạo ra "lười biếng", tức là nó chỉ được tạo khi bạn sử dụng lần đầu tiên.
Mô hình mô-đun: trong "phong cách dễ đọc hơn". Bạn có thể dễ dàng thấy phương thức nào là công khai và phương thức nào là tư nhân
var module = (function(_name){
/*Local Methods & Values*/
var _local = {
name : _name,
flags : {
init : false
}
}
function init(){
_local.flags.init = true;
}
function imaprivatemethod(){
alert("hi im a private method");
}
/*Public Methods & variables*/
var $r = {}; //this object will hold all public methods.
$r.methdo1 = function(){
console.log("method1 call it");
}
$r.method2 = function(){
imaprivatemethod(); //calling private method
}
$r.init = function(){
inti(); //making init public in case you want to init manually and not automatically
}
init(); //automatically calling init method
return $r; //returning all publics methods
})("module");
bây giờ bạn có thể sử dụng các phương thức công khai như
mô-đun.method2 (); // -> Tôi đang gọi một phương thức riêng tư trong một cảnh báo phương thức công khai ("hi im một phương thức riêng tư")
Người độc thân:
Đảm bảo một lớp chỉ có một thể hiện và cung cấp một điểm truy cập toàn cầu vào nó.
Mẫu Singleton giới hạn số lượng phiên bản của một đối tượng cụ thể chỉ là một đối tượng. Trường hợp duy nhất này được gọi là singleton.
Đối tượng Singleton được triển khai như một chức năng ẩn danh ngay lập tức. Hàm thực thi ngay lập tức bằng cách gói nó trong ngoặc theo sau hai dấu ngoặc bổ sung. Nó được gọi là ẩn danh vì nó không có tên.
Chương trình mẫu,
var Singleton = (function () {
var instance;
function createInstance() {
var object = new Object("I am the instance");
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
function run() {
var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();
alert("Same instance? " + (instance1 === instance2));
}
run()
Đơn giản nhất / Sạch nhất đối với tôi có nghĩa là cũng đơn giản để hiểu và không có tiếng chuông & còi như được thảo luận nhiều trong phiên bản Java của cuộc thảo luận:
Một cách hiệu quả để thực hiện một mẫu đơn trong Java là gì?
Câu trả lời phù hợp nhất / đơn giản nhất theo quan điểm của tôi là:
https://stackoverflow.com/a/70824/1497139
Và nó chỉ có thể được dịch một phần sang JavaScript. Một số khác biệt trong Javascript là:
Nhưng với cú pháp ECMA mới nhất, có thể kết hợp với:
Mẫu đơn như ví dụ lớp JavaScript
class Singleton {
constructor(field1,field2) {
this.field1=field1;
this.field2=field2;
Singleton.instance=this;
}
static getInstance() {
if (!Singleton.instance) {
Singleton.instance=new Singleton('DefaultField1','DefaultField2');
}
return Singleton.instance;
}
}
Cách sử dụng ví dụ
console.log(Singleton.getInstance().field1);
console.log(Singleton.getInstance().field2);
Kết quả ví dụ
DefaultField1
DefaultField2
function Once() {
return this.constructor.instance || (this.constructor.instance = this);
}
function Application(name) {
let app = Once.call(this);
app.name = name;
return app;
}
Nếu bạn vào lớp:
class Once {
constructor() {
return this.constructor.instance || (this.constructor.instance = this);
}
}
class Application extends Once {
constructor(name) {
super();
this.name = name;
}
}
Kiểm tra:
console.log(new Once() === new Once());
let app1 = new Application('Foobar');
let app2 = new Application('Barfoo');
console.log(app1 === app2);
console.log(app1.name); // Barfoo
Nếu bạn muốn sử dụng các lớp:
class Singleton {
constructor(name, age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
}
let x = new Singleton('s',1);
let y = new Singleton('k',2);
Đầu ra cho ở trên sẽ là:
console.log(x.name,x.age,y.name,y.age) // s 1 s 1
Một cách khác để viết Singleton bằng chức năng
function AnotherSingleton (name,age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
let a = new AnotherSingleton('s',1);
let b = new AnotherSingleton('k',2);
Đầu ra cho ở trên sẽ là:
console.log(a.name,a.age,b.name,b.age)// s 1 s 1