JS use get in constructor - javascript

In a "basic" object, it's easy to define a 'get' property.
var anObject = {
get aProperty() {
return "abc";
}
}
document.write(anObject.aProperty); //abc
I find a solution to add a get property in a constructor function.
var BasicConstructor = function ()
{
Object.defineProperty(this, "aProperty", {get : function(){ return "abc"; }});
}
var anOtherObject = new BasicConstructor ();
document.write(anOtherObject.aProperty); //abc
Is their a more simple and readable solution ? I try some solution like the one below without success.
var BasicConstructor = function ()
{
this.aProperty = get ()
{
return "abc";
}
}
var anOtherObject = new BasicConstructor ();
document.write(anOtherObject.aProperty); //abc

Since your question is tagged with ecmascript-6
You can just use es6 class syntax and a getter:
class BasicConstructor {
get aProperty() { return 'abc'; }
};
var anOtherObject = new BasicConstructor();
document.write(anOtherObject.aProperty); //abc

this.aproperty = get () {} is invalid syntax. you need the "function" keyword (and you don't really need the get at all, but you can keep it if you want)
var BasicConstructor = function ()
{
this.aProperty = function get ()
{
return "abc";
}
}
var anOtherObject = new BasicConstructor ();
document.write(anOtherObject.aProperty()); //abc

Related

How to reuse object constructor?

This is how I create objects from a hash of properties:
var object = new function (data) {
var self = this;
self.property = data.property;
self.anotherProperty = data.anotherProperty;
self.method = function () { return 'something'; }
self.update = function (newData) {
//what is here ?
//i could have written:
self.property = newData.property;
self.anotherProperty = newData.anotherProperty;
//but why not reuse the constructor?
}
};
I wonder how to reuse this function (constructor) to update an object from hash.
So that:
object.update(newData)
would update current object properties from newData hash the same way it is done in the constructor function.
By giving the constructor a name?
function MyNotReallyClass(data){
var self = this;
self.property = data.property;
self.method = function () { return 'something'; }
self.update = MyMyNotReallyClass;
};
you can can now call
var obj = new MyNotReallyClass(data);
var obj2 = new MyNotReallyClass(data);
and
obj.update(data);
i hope this helps.. i not 100% sure, because i'm learning too.. but yeah try it ;)
edit: after reading this comment of you: "But that would return a new instance, wouldn't it? Which i don't want."
i think you can write the Update function and call it in your constructor
var object = new function (data) {
var self = this;
self.update = function (newData) {
self.property = data.property;
self.method = function () { return 'something'; }
// and other things You want to do in constructor and update
}
self.update(data);
}
;

Using "dot" inside a prototype name in JavaScript

Lets say I have this class:
function classA(n){
this.name = n
}
classA.prototype.getName = function(){
return this.name
}
var x = new classA('john')
console.log(x.getName())
My question is: can I group multiple methods inside a namespace? So I would like to do that:
var x = new classA('john')
console.log(x.CONSTANT.getName())
So I would like to call some methods as x.someMethod() and others as x.CONSTANT.otherMethod()
PS: I'm looking for a cross-browser method. Bind is not working in Safari and IE9.
You can do it, for example, via bind. Google es5 shim for implementation of bind in browsers, which don't support it natively.
function MyClass(name) {
this.name = name;
this.CONSTANT.otherMethod = this.CONSTANT.otherMethod.bind(this);
}
MyClass.prototype.CONSTANT = {
otherMethod: function() {
alert(this.name);
}
};
As far as I know a constant is just a property and it can't contain methods, you need to separate your objects and use methods to have the same effect:
function A (id) {
this.id = id;
this.showId = function () { return this.id; }
};
function B (a) {
this.a = a;
this.getA = function () { return this.a; }
}
var a = new A(12);
var b = new B(a);
b.getA().showId();
edit:
You can use a literal object as follow
function B (id) {
this.id = id;
this.CONSTANT = { otherMethod: function () { alert("..."); } };
someMethod = function () { return this.id; }
}
but the literal CONSTANT object can't access B-object methods,
Consider the #kirilloid post to round this.
You can, but you have to be careful because it won't act like you think it will. The this for the method will be the namespace, not the root object.
For example, in x.CONSTANT.getName(), the this object will be x.CONSTANT, and not x.
Here's some sample code which kinda does what you ask (or in jsfiddle):
function MyClass() {}
MyClass.prototype.CONSTANT = {
getName: function() {
alert('Foo');
}
};
var c = new MyClass();
c.CONSTANT.getName();
To make sure the this is right, you need to do much more.
You can use getters/setters (read this article) to achieve this. For example you may define it like this:
classA.prototype.__defineGetter__('CONSTANT', function() {
var that = this;
return {
getName: function() {
return that.name;
}
};
});
Note that holding reference to the object. It will work now
x = new classA('test');
x.CONSTANT.getName();
// result - test

OO Javascript Question

Given the following:
var someObject = {};
someObject.prototype.a = function() {
};
someObject.prototype.b = function() {
//How can I call someObject.a in this function?
};
How can I call someObject.a from someObject.b? Thanks.
This will work:
someObject.prototype.b = function() {
this.a();
};
However your definition of someObject is slightly wrong, it should be:
var someObject = function() {};
Test script:
var someObject = function() {};
someObject.prototype.a = function() {
alert("Called a()");
};
someObject.prototype.b = function() {
this.a();
};
var obj = new someObject();
obj.b();
I think you probably meant to do this:
function Thingy() {
}
Thingy.prototype.a = function() {
};
Thingy.prototype.b = function() {
this.a();
};
var someObject = new Thingy();
It's constructor functions, not plain objects, that have a special prototype property. The prototype of a constructor function is assigned to all objects created with that constructor via the new keyword as their underlying prototype, which gives them default properties (which may reference functions, as they do above).

How to emulate a constructor with ES5 Object.create and object literal syntax?

Presume I have an object like this:
var Foo = {
x: 5,
sprite: new Image()
}
Problem: I want to initialize that sprite with the right src. However, when I use the following creation technique:
var f = Object.create(Foo);
I don't have a constructor method (aka init function) to setup sprite.src = 'cool.png';
My question:
If I am using the object literal technique, and Object.create(), when do I actually initialize some of my internal state (like the example of the new Image())
My solution:
var Foo = {
create: function() {
var f = Object.create(Foo);
f.sprite.src = 'cool.png';
return f;
}
}
However, I don't know if that's a great pattern. I'd like to do this the "JavaScript Way" if there is a way. :)
Thanks!
I do something very similar to what you've written above, but I combine it with the module pattern:
var Vehicle = (function(){
var exports = {};
exports.prototype = {};
exports.prototype.init = function() {
this.mph = 5;
};
exports.prototype.go = function() {
console.log("Going " + this.mph.toString() + " mph.");
};
exports.create = function() {
var ret = Object.create(exports.prototype);
ret.init();
return ret;
};
return exports;
})();
From the outside, this exposes Vehicle.create() and Vehicle.prototype. Then if I want to make a Derived type, I can do this:
var Car = (function () {
var exports = {};
exports.prototype = Object.create(Vehicle.prototype);
exports.prototype.init = function() {
Vehicle.prototype.init.apply(this, arguments);
this.wheels = 4;
};
exports.create = function() {
var ret = Object.create(exports.prototype);
ret.init();
return ret;
};
return exports;
})();
This pattern lets me derive types without making the error of Car.prototype = new Vehicle(), which is fail if my constructors take parameters.
As I can assume from this link you should do something like:
function ImgInstance(src){
var img=new Image();
img.src=src;
return img;
}
Object.create(Foo, {sprite: {value: ImgInstance("url")}});
I think this article sums it up pretty nicely:
http://www.bennadel.com/blog/2184-Object-create-Improves-Constructor-Based-Inheritance-In-Javascript-It-Doesn-t-Replace-It.htm
I would simply do this:
function Image(src) {
this.src = src;
}
function Foo() {
this.x = 5;
this.sprite = new Image('cool.png');
}
To cut a long story short: Don't try. The basic idea of Object.create is avoiding constructor functions. You're better off using this good old pattern:
var Foo = function (url) {
//this.sprite.src = url; // This will overwrite the prototype's src
this.sprite = new Image();
this.sprite.src = url;
};
Foo.prototype = {
x: 5,
sprite: new Image() // do you really want this?
};
Then use new Foo instead of Object.create.

How to make a JavaScript singleton with a constructor without using return?

I currently know two ways to construct singletons in JavaScript. First:
var singleton = {
publicVariable: "I'm public",
publicMethod: function() {}
};
It is perfect except that it does not have a constructor where I could run initialization code.
Second:
(function() {
var privateVariable = "I'm private";
var privateFunction = function() {}
return {
publicVariable: "I'm public",
publicMethod: function () {}
}
})();
The first version does not have private properties nor does it have a constructor, but it is faster and simpler. The second version is more complex, ugly, but has a constructor and private properties.
I'm not in a need for private properties, I just want to have a constructor. Is there something I am missing or are the two approaches above the only ones I've got?
function Singleton() {
if ( Singleton.instance )
return Singleton.instance;
Singleton.instance = this;
this.prop1 = 5;
this.method = function() {};
}​
Here is my solution with closures:
function Singleton() {
Singleton.getInstance = (function(_this) {
return function() { return _this; };
})(this);
}
Test:
var foo = new Singleton();
var bar = Singleton.getInstance();
foo === bar; // true
If you are just looking for a place to initialise your singleton, how about this?
var singleton = {
'pubvar': null,
'init': function() {
this.pubvar = 'I am public!';
return this;
}
}.init();
console.assert(singleton.pubvar === 'I am public!');
Simple and elegant.
var singleton = new function() { // <<----Notice the new here
//constructorcode....
this.publicproperty ="blabla";
}
This is basically the same as creating a function, then instantly assiging a new instace of it to the variable singleton. Like var singleton = new SingletonObject();
I highly advice against using singletons this way in javscript though because of the execution order is based on where in the file you place the object and not on your own logic.
What about this?
var Singleton = (function() {
var instance;
// this is actual constructor with params
return function(cfg) {
if (typeof instance == 'undefined') {
instance = this;
this.cfg = cfg;
}
return instance;
};
})();
var a = new Singleton('a');
var b = new Singleton('b');
//a === b; <-- true
//a.cfg <-- 'a'
//b.cfg <-- 'a'
I make it an actual Singleton with static functions and no this like so:
class S {
//"constructor"
static init() {
//Note: Since it's a singleton, there's no "this" instance.
//Instead, you store variables directly on the class.
S.myVar = 7;
}
static myOtherFunc() {
alert(S.myVar);
}
}
//Immediately call init() to make it the "constructor".
//Alternatively, you can call init() elsewhere if you'd
//like to initialize it at a particular time.
S.init();
//Later:
S.myOtherFunc();
S.myVar = 10;

Categories