OO Javascript Question - javascript

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

Related

can't use Object.create to create object inside an object in javascript

Let's say I have the following code:
(function($) {
var Obj = {
init: function() {
var c1 = Object.create(this.MyChild);
var c2 = Object.create(this.MyChild);
c1.init(); //not working!!!
},
MyChild: function() {
this.init = function() {
console.log('calling MyChild init function');
}
}
};
Obj.init();
})(jQuery);
When creating Obj, I used object literal as I don't need to create the instance of it, and when creating MyChild objects, I used the constructor function and used Object.create as I need to create multiple instances of MyChild.
However, when I call Object.create, it doesn't work, when c1.init() is called, it says the init function is undefined, but if I replaced Object.create(this.MyChild) to:
var c1 = new this.MyChild();
c1.init();
why?
Object.create(func) doesn't do the same thing as new func()!
Object.create() creates an (otherwise empty!) object, which prototype will be set to the object, that is passed to that function (MDN)
To use Object.create() in your example, you could modify it like this:
(function($) {
var Obj = {
init: function() {
var c1 = Object.create(this.MyChild);
var c2 = Object.create(this.MyChild);
c1.init(); //not working!!!
},
MyChild: {
init: function() {
console.log('calling MyChild init function');
}
}
};
Obj.init();
})(jQuery);
But in this case everything will just POINT to your MyChild object. Properties of MyChild will be shared among every object, that you create using Object.create().
I think you should use
var c1 = Object.create(this.MyChild.prototype);
instead of
var c1 = Object.create(this.MyChild);

How can I invoke a prototype function inside of a function object it b

var func_obj = function() {
console.log('wat');
this.my_proto_method();
};
func_obj.prototype.my_proto_method = function() {
console.log('how do I programming');
};
​func_obj();​
I'm trying to get the above code to work. From what I've read this should work, not sure what I'm doing wrong here. Also setup a fiddle here
To access prototype object/method with this you have to create new instance of func_obj. If you want to access prototype methods withod instance then you have to use prototype property as func_obj.prototype.my_proto_method().
var func_obj = function() {
console.log('wat');
this.my_proto_method();
// if called without new then access prototype as : func_obj.prototype.my_proto_method()
};
func_obj.prototype.my_proto_method = function() {
console.log('how do I programming');
};
​new func_obj();​
You need to prefix your call to func_obj with the new prefix:
var func_obj = function() {
console.log('wat');
this.my_proto_method();
};
func_obj.prototype.my_proto_method = function() {
console.log('how do I programming');
};
​var foo = new func_obj();​

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

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