Js: How to reference> property constructor from another constructor - javascript

I want to reference a property in Constructor1 (property1) from Constructor2
and I thought, it was ok by doing this... or should I nest the constructor2 inside the constructor1?
var Constructor2 = function() {
this.method2 = function() {
// how to reference Constructor1.property ???
};
};
var Constructor1 = function() {
this.property1 = true;
this.property2 = false;
this.method1 = new Constructor2();
};
var inst = new Constructor1();
inst.method1.method2();

This seems an example of the delegation pattern.
Your "class" Constructor1 is delegating part of its logic to the "class" Constructor2.
Constructor2 needs to access the properties of the delegator and this can be done passing an instance of the delegator to the delegate:
var Constructor2 = function(delegator) {
this.delegator = delegator;
this.method2 = function() {
console.log(delegator.property1);
};
};
var Constructor1 = function() {
this.property1 = true;
this.property2 = false;
this.method1 = new Constructor2(this);
};
var inst = new Constructor1();
inst.method1.method2();
I think that it would be better to consider Constructor1 and Constructor2 not as constructors but as classes. I understand that they are functions and that they are used to create objects, but usually they get the name of the class they will instantiate.

Related

Javascript prototype method "Cannot set property"

I'm always getting Cannot set property 'saySomething' of undefined but why?
Am I making a mistake somewhere?
var Person = new Object();
Person.prototype.saySomething = function ()
{
console.log("hello");
};
Person.saySomething();
Debugging tip: You get this ..of undefined errors when you try to access some property of undefined.
When you do new Object(), it creates a new empty object which doesn't have a prototype property.
I am not sure what exactly are we trying to achieve here but you can access prototype of function and use it.
var Person = function() {};
Person.prototype.saySomething = function() {
console.log("hello");
};
var aperson = new Person();
aperson.saySomething();
The prototype property exists on functions, not on instantiated objects.
var Person = new Object();
console.log(Person.prototype); // undefined
var Person2 = function () {}
console.log(Person2.prototype); // {}
This is useful because things put on the prototype of a function will be shared by all object instances created with that function (by using new).
var Person = function() {};
Person.prototype.saySomething = function() {
console.log("hello");
};
console.log(
new Person().saySomething === Person.prototype.saySomething // true. they are the same function
);
If all you want is to add a method to the person object, there's no need for a prototype:
var Person = {};
Person.saySomething = function() {
console.log("hello");
};
Person.saySomething();
You can even use object literal syntax:
var Person = {
saySomething: function() {
console.log("hello");
}
};
Person.saySomething();
i was trying out some code thought of posting it, might help others.
<script>
var MODULE = {};
MODULE = (function (my) {
my.anotherMethod = function () {
console.log("hello ");
};
my.newMethod = function(){
console.log("hi new method ");
}
return my;
}(MODULE));
MODULE.anotherMethod();
MODULE.newMethod();
</script>
And please not var MODULE ={}, if this is not initialized with {} then it give cannot set property.
I know i am late to the party but as you see there is no satisfying answer available to the question so i am providing my own.
In your case when you write
var Person = new Object();
you are creating an instance of Object type.
You can add a property using prototype property to the Object, not to the instance of Object.which you can use by the instance laterly.
so you can define like
Object.prototype.saySomething = function ()
{
console.log("hello");
};
now you can call it like this.
Person.saySomething();
You can check here.
var Person = function(name) {
this.canTalk = true;
this.name = name;
};
Person.prototype.greet = function() {
if (this.canTalk) {
console.log('Hi, I am ' + this.name);
}
};
bob = new Person('bob');
bob.greet();

What is the best way to use this in prototype method

It is comfortable to create self = this variable. In all methods we always can use self, and don't worry about method context - some times this in method not we expected.
But in prototype method we can't use this hint;
Look at the example (jQuery needed onle to show the question)
var myClass = function () {
this.propery = 'someData';
var self = this;
this.method = function () {
console.log(self.propery);
}
}
myClass.prototype.method2 = function () {
// want to use self here
console.log(this);
}
var my = new myClass();
var eventBus = $({});
eventBus.bind('onMyEvent', my.method);
eventBus.bind('onMyEvent', my.method2);
eventBus.trigger('onMyEvent');
What is the best way to declare the class with possibility to use self in prototype methods?
You don't need self, just need to set the value of this by binding the object to the function:
var MyClass = function () {
this.property = 'someData';
this.method = function () {
console.log(this.property);
};
};
MyClass.prototype.method2 = function () {
console.log(this);
};
var my = new MyClass();
var eventBus = $({});
eventBus.bind('onMyEvent', my.method.bind(my)); // bind
eventBus.bind('onMyEvent', my.method2.bind(my)); // bind
eventBus.trigger('onMyEvent');

How can I use a method from inherited class

I have the inheritance chain Vehicle -> Motorized -> Car implemented:
function Vehicle()
{
var m_name;
this.setName = function(pName) {
m_name = pName;
};
this.getName = function() {
return m_name;
};
}
function Motorized()
{
var m_started = false;
this.start = function() {
m_started = true;
console.log(getName() + " started");
};
}
function Car()
{ }
//set up the inheritance chain
Motorized.prototype = new Vehicle();
Car.prototype = new Motorized();
// use
var lCar = new Car;
lCar.setName("Focus");
console.log(lCar.getName()); // Focus
lCar.start(); // ReferenceError: getName is not defined
When I invoke lCar.start() (defined in function Motorized), I get an ReferenceError: getName is not defined. How can I use the inherted method getName() in my subclass Motorized?
Because Javascript doesn't know where to look for your getName() method. You can clarify the syntax declaring a self variable that always points to the right object, like this:
function Vehicle()
{
var self = this; // Vehicle
var m_name;
this.setName = function(pName) {
self.m_name = pName;
};
this.getName = function() {
return self.m_name;
};
}
function Motorized()
{
var self = this; // Motorized
var m_started = false;
this.start = function() {
/*
`self` is Motorized, with proto Vehicle, so
has a getName() method.
`this` instead is the object where you call
start() from, i.e. Car, in the example down below.
*/
self.m_started = true;
console.log(self.getName() + " started");
};
}
function Car()
{ }
//set up the inheritance chain
Motorized.prototype = new Vehicle();
Car.prototype = new Motorized();
// use
var lCar = new Car;
lCar.setName("Focus");
console.log(lCar.getName()); // Focus
lCar.start(); // Focus started
Note that in this case, using the keyword this instead of self throughout the code would have worked as well, but you definitely cannot omit it before getName(). Also, if you are planning to add more code later on, such as event handlers in jQuery, having a clear reference to the class you're coding in can be useful, as this can become easily ambiguous, at least from the human point of view.
Anyway, whether using self is a bad coding pattern or not is the topic of this question; the point in your example is that you need to call self.getName() or this.getName().

How to reference self in a new javascript function?

I am trying to make a "Class" factory with Javascript so that I can create different types of objects.
Here is the function I'm using:
var Class = function(methods) {
var klass = function() {
var self = this;
this.initialize.apply(this, arguments);
};
for (var property in methods) {
klass.prototype[property] = methods[property];
}
if (!klass.prototype.initialize) klass.prototype.initialize = function(){};
return klass;
};
Then I can do:
var myObject = Class({
initialize: function() { console.log(self);}
});
var createdObject = new myObject();
However, the console.log(self) is always referring to Window, and I'd like it to refer to the object itself.
I know this is a scope issue, but I'm confused on how to create a reference to the object?
I am trying to make a "Class" factory with Javascript so that I can create different types of objects.
Here is the function I'm using:
var Class = function(methods) {
var klass = function() {
var self = this;
this.initialize.apply(this, arguments);
};
for (var property in methods) {
klass.prototype[property] = methods[property];
}
if (!klass.prototype.initialize) klass.prototype.initialize = function(){};
return klass;
};
Then I can do:
var myObject = Class({
initialize: function() { console.log(self);}
});
var createdObject = new myObject();
However, the console.log(self) is always referring to Window, and I'd like it to refer to the object itself.
I know this is a scope issue, but I'm confused on how to create a reference to the object?
For example, if I wanted to do:
var myObject = Class({
initialize: function() {
$('#myDiv').click( function() {
self.anotherFunction();
});
},
anotherFunction: function() {
alert('hi');
}
});
I would need to be able to reference the "myObject" with self...
Use this instead of self. self will not be accessible to initialize function as it is defined outside the scope of klass self
Best option is define self inside each function as last solution I provided.
var myObject = Class({
initialize: function() { console.log(this);}
});
OR
var myObject = Class({
initialize: function() { console.log(createdObject);}
});
OR
var myObject = Class({
initialize: function() { var self = this; console.log(self );}
});

Javascript prototypal inheritance and OOP

I'm creating an application that allows a user to create widgets. There are several different types of widgets, and I have defined them using protypal inheritance. i.e.
//the base widget that all widgets inherit from
var Widget = function(){}
Widget.prototype.someFunction = function(){}
//widget type A
var A = function(){}
A.prototype = new Widget();
//widget type B
var B = function(){}
B.prototype = new Widget();
I have discovered that it will be convenient to add a method on the base class that can create a new widget instance of the same type. i.e.
//the base widget
var Widget = function(){};
Widget.prototype.clone = function(){
switch(this.type){
case 'A':
return new A();
break;
case 'B':
return new B();
break;
default:
break;
}
};
Which would allow me to get a new widget of the same type using the following code:
var widgetTypeA = new A();
var cloneOfWidgetTypeA = widgetTypeA.clone();
My concern is that the base widget now has to be explicitly aware of each of the types of widgets that inherit from it. Does this violate any principles of good OOP?
Widget.prototype.clone = function() {
var constructor = window[this.type];
return new constructor();
};
Assuming that all your subclasses are declared as globals of course.
But honestly I would out those sub classes in the Widget namespace, and access them through it rather than making everything global.
Widget.A = function(){};
Widget.A.prototype = new Widget();
Widget.prototype.clone = function() {
var constructor = Widget[this.type];
return new constructor();
};
Given that your constructors are globals, you could do something like:
var global = this;
Widget.prototype.clone = function() {
if (global[this.type])
return new global[this.type]();
};
Provided each instance has a type property whose value is the name of the constructor. Or you could fix the constructor property of constructor's prototype and do:
Widget.prototype.clone = function() {
return new this.constructor();
};
function A() { };
A.prototype = new Widget();
A.prototype.constructor = A;
var a = new A();
var aa = a.clone();
However, that assumes that you don't have any parameters to pass. If you do have parameters to pass, then you likely have to know which type you are making and so can call the correct constructor anyway.
If ECMA5 is supported:
use Object.create(Object.getPrototypeOf(this));
If ECMA5 is not supported:
create an anonymous function
set the prototype of the anonymous function to the non-standard attribute this.__proto__
Example:
var Widget = function() { };
Widget.prototype.clone = function() {
/*
Non-ECMA5:
var newClone = function() {};
newClone.prototype = this.__proto__;
return new newClone();
*/
// ECMA5
return Object.create(Object.getPrototypeOf(this));
}
var A = function() { };
A.prototype = new Widget();
A.prototype.name = "I'm an A";
var B = function() { };
B.prototype = new Widget();
B.prototype.name = "I'm a B";
var x1 = new A();
var y1 = x1.clone();
console.log("y1 should be A: %s", y1.name);
var x2 = new B();
var y2 = x2.clone();
console.log("y2 should be B: %s", y2.name);
The information you need is already available in the constructor property. However, overwriting prototype will lose it as I recently explained here.
Using my own class implementation for ECMAScript version 3 or version 5, your example would look like this:
var Widget = Class.extend({
someFunction : function() {
alert('someFunction executed');
},
clone : function() {
return new this.constructor;
}
});
var A = Widget.extend();
var B = Widget.extend({
constructor : function(arg) {
Widget.call(this); // call parent constructor
this.arg = arg;
},
// override someFunction()
someFunction : function() {
alert('someFunction executed, arg is ' + this.arg)
},
// clone() needs to be overriden as well:
// Widget's clone() doesn't know how to deal with constructor arguments
clone : function() {
return new this.constructor(this.arg);
}
});
var a = new A;
var a2 = a.clone();
a2.someFunction();
var b = new B(42);
var b2 = b.clone();
b2.someFunction();

Categories

Resources