Simple JS example of Singleton Pattern not working - javascript

I made a simple example of Singleton Pattern but it is giving blank objects in both cases. Please someone help?
var a = ( function(){
var instance = {};
function init() {
return {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
}
return {
getInstance: function(){
if(!instance) {instance = init();}
return instance;
}
}
})();
console.log(a.getInstance());
console.log(a.getInstance());

As I said in a comment, the problem is that instance is initialized to {}, which is truthy, so !instance will never be true.
There's only one instance variable, created for the one call to your anonymous function. That's the whole point of having it, it tracks the singleton. So initialize it with a falsy value (or leave it with the default undefined, which is falsy):
var a = ( function(){
var instance = null;
function init() {
return {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
}
return {
getInstance: function(){
if(!instance) {instance = init();}
return instance;
}
}
})();
const first = a.getInstance();
console.log(first);
const second = a.getInstance();
console.log(second);
console.log(first === second); // true
.as-console-wrapper {
max-height: 100% !important;
}
That said, you only need all of this complexity if you want late initialization. Otherwise, just create the object:
var a = {
instance = {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
};
Then a.instance is the singleton. If you want it to be non-writable:
var a = Object.defineProperty({}, "instance", {
value: {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
});
(That will also be non-enumerable. If you want it to be enumerable, add enumerable: true.)
Or just:
var instance: {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
};
If you want that to be read-only, use const in any modern environment:
const instance: {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
};
In all of the above, remember that although you may have a singleton, and although the instance property/constant may be read-only, nothing about the object itself is immutable. Properties can be added, removed, changed, etc. To prevent that, use Object.freeze.

If in case this can be a variety to T.J. Crowder answer, You may create an instance once and save it to a variable, then every time the method is called, you may return that variable. I think closure plays a role here.
var a = ( function(){
var instance = {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
};
return {
getInstance: function(){
return instance;
}
}
})();
let b = a.getInstance();
let c = a.getInstance();
console.log(b);
console.log(c);
console.log( b === c )

Related

What are the performance drawbacks of using global symbols in a getter and setter methods?

The JavaScript code below has a getter and setter for name using global symbols, and age_ using a dangling underscore.
JavaScript Code
function Human(name, age) {
this.name = name;
this.age_ = age;
}
Human.prototype.greet = function() {
console.log(`Hello ${this.name}! You are ${this.age} years old.`);
};
Human.prototype[Symbol.iterator] = function* () {
yield* Object.getOwnPropertyNames(this);
yield* Object.getOwnPropertySymbols(this);
};
Object.defineProperties(
Human.prototype,
{
name: {
get() {
return this[Symbol.for('name')];
},
set(value) {
this[Symbol.for('name')] = value;
},
},
age: {
get() {
return this.age_;
},
set(value) {
this.age_ = value;
},
},
},
);
let mary = new Human('Mary Smith', 18);
mary.greet();
console.dir(mary);
let john = new Human('John Doe', 25);
john.greet();
console.dir(john);
Console Output
I want to know is there any performance drawbacks to using global symbols for a getter and setter methods because I find it much cleaner code.

Assigning functions to Objects

I want to add functions to JSON Objects, but I can't find function for assigning to all objects, only to one.
This code works with Arrays:
Object.defineProperty(Array.prototype, 'random', {
value: () => {
return this[Math.floor(Math.random() * this.length)];
},
});
I've also found this code:
const obj = {name: 'Bob'};
obj.fullName = function() { return this.name }
But that one only works for specific object, not all of them.
Is it event possible to write global functions for all JSON Objects, and if is, then how to do it?
You could add the function to Object.prototype. Note that this is not considered a very good practice because it could impact the rest of the code (like shown in the comments):
Object.prototype.fullName = function() { return this.name; };
const obj = { name: 'Bob' };
console.log(obj.fullName());
You should consider doing this instead:
const baseObject = { fullName: function() { return this.name; } };
const obj = Object.create(baseObject, { name: { value: 'Bob', writable: true } });
console.log(obj.fullName());
And if your target runtime (browser?) supports ECMAScript 6, you could also create a dedicated class for this:
class MyClass {
constructor(name) {
this.name = name;
}
fullName() { return this.name; }
}
const bob = new MyClass('Bob');
console.log(bob.fullName());
Finally, the class syntax for ECMAScript 5:
function MyClass(name) {
this.name = name;
}
MyClass.prototype.fullName = function() { return this.name; }
const bob = new MyClass('Bob');
console.log(bob.fullName());

What is React's createClass's parameter look like exactly? Is it an object?

I feel like I've seen both versions of React's creatClass, with the former being more apparent in the docs. Is there any differences between the 2 other than the stylistic ones? Just seems weird that the first style looks like it's accepting an object, whereas the second is just a scope with any functions you want to throw at it.
var Greeting = React.createClass({
someFunction: function () {
...
},
getDefaultProps: function() {
return {
name: 'Mary'
};
},
// ...
});
vs.
var Greeting = React.createClass({
someFunction () {
...
}
getDefaultProps () {
return {
name: 'Mary'
};
}
// ...
});
This is not with react. It is a ES6 feature called Object Literals
const a = 10;
const b = {
a, //which is equal to a: a
}
function a(){}
const c = {
a, //which is equal to a: function a(){}
}

Acess to this from subobject in JavaScript

How do I get access to the properties or method of the main object, from sub-obiect level two (sub3). If possible I would like to avoid solutions chaining return this.
Obj = function () {};
Obj.prototype = {
name: 'name',
main: function(){
console.log(this.name);
},
subobject: {
sub2: function () {
console.log(this);
},
sub3: function () {
console.log(this.name); // How access to Obj.name ??
}
}
}
o = new Obj();
o.main(); // return name
o.subobject.sub2(); // return subobject
o.subobject.sub3(); // return undefined
With your current syntax, you can't. Because for sub2 and sub3, the this variable is Obj.prototype.subobject.
You have multiple choice:
The obvious one: don't use a suboject.
Create subobject, sub2 and sub3 in the constructor
Obj = function() {
var self = this;
this.subobject = {
sub1: function() { console.log(self); }
}
}
Use bind at each call:
o.subobject.sub2.bind(o)();

javascript: Define reference in nested object to parent object

I have following object:
var myObject = {
attributes: { name: "dev.pus", age: 29 },
someInjectedObject: {
name: "someComponent",
action: function() {
// do something
return this.this.attributes.name; // this surely won't work :(
}
}
};
As you see I want to get myObject.attributes.name from an nested part of the object without having to observe the value.
How do I do this? How do I define a reference?
EDIT:
A simple myObject.attributes isn't enough because myObject changes or better gets assigned to a new variable.
Create a closure around your object:
var myObject = (function() {
var result = {
attributes: { name: "dev.pus", age: 29 },
someInjectedObject: {
name: "someComponent",
action: function() {
// do something
return result.attributes.name;
}
};
};
return result;
})();
You can do refer to myObject directly like this:
var myObject = {
attributes: { name: "dev.pus", age: 29 },
someInjectedObject: {
name: "someComponent",
action: function() {
// do something
return myObject.attributes.name; // this surely will work :(
}
}
};
alert(myObject.someInjectedObject.action());
​
DEMO
​

Categories