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 );}
});
Related
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.
I understand it is in general bad practice to modify prototypes with the object.prototype.whatever syntax when using knockout, but I'm trying to understand why this isn't working at all:
var Foo = function() {
var self = this;
self.bar = ko.observable("bar");
};
Foo.prototype.capitalizer = function() {
self.bar("Bar");
};
var vm = function() {
var self = this;
self.whatever = new Foo();
};
js fiddle here: http://jsfiddle.net/vvdo7z70/8/
when this works as expected:
var Foo = function() {
var self = this;
self.bar = ko.observable("bar");
self.capitalizer = function() {
self.bar("Bar");
}
};
var vm = function() {
var self = this;
self.whatever = new Foo();
};
js fiddle here: http://jsfiddle.net/vvdo7z70/10/
Is it just not possible to pass relevant ko bindings with the object.prototype syntax? or is there another way to do it?
For one, self isn't defined in Foo.prototype.capitalizer. Once that's fixed, you need to note that the binding click: whatever.capitalizer is using the function, not the method, which is to say, the whatever context is not provided. Instead, vm is provided as the context. This will work:
Foo.prototype.capitalizer = function () {
this.whatever.bar("Bar");
};
or
click: whatever.capitalizer.bind(whatever)
If I have the following:
var ObjectA = Ember.Object.extend({
init: function() {
this._super();
document.write('init object A<br>');
}
});
var ObjectB = ObjectA.extend({
init: function() {
this._super();
document.write('init object B<br>');
}
});
var ObjectC = ObjectB.extend({
init: function() {
this._super();
document.write('init object C<br>');
}
});
var myobj = ObjectC.create();
How do I make it so that ObjectC's init() method does not call ObjectB's init method?
http://jsfiddle.net/QYKb3/
This was answered by raycohen in #emberjs. Of course the answer was simple, and simply involved calling ObjectA's prototype:
ObjectA.prototype.init.call(this);
Updated fiddle: http://jsfiddle.net/QYKb3/1/
How can i get variable in handler function of obj? Without reference of the obj in MyClass.
var obj = {
func: function(){
var myClass = new MyClass();
myClass.handler = this.handler;
myClass.play();
},
handler: function(){
//Here i don't have access to obj
console.log(this); //MyClass
console.log(this.variable); //undefined
},
variable:true
};
function MyClass(){
this.play = function(){
this.handler();
};
this.handler = function(){};
};
obj.func();
That's construction need you, if you use Base.js or another similar way of oop.
_.bindAll(obj) (underscore metod) also not suitable. It's break overriding in Base.js.
Bind only handler method: http://jsfiddle.net/uZN3e/1/
var obj = {
variable:true,
func: function(){
var myClass = new MyClass();
// notice Function.bind call here
// you can use _.bind instead to make it compatible with legacy browsers
myClass.handler = this.handler.bind(this);
myClass.play();
},
handler: function(){
console.log(this.variable);
}
};
function MyClass(){
this.play = function(){
this.handler();
};
this.handler = function(){};
};
obj.func();
Use a variable to refer original context:
...
var self = this;
myClass.handler = function(){ self.handler(); };
...
Declare variable before handler:
var obj = {
variable: true,
func: function(){
// ...
},
handler: function(){
console.log(this.variable); //true
}
};
Use Function call with this from obj in declared in a scope var to solve it.
var obj = {
func: function(){
var self = this;
var myClass = new MyClass();
myClass.handler = function() { return this.handler.call(self); };
myClass.play();
},
handler: function(){
//Here i don't have access to obj
console.log(this); //MyClass
console.log(this.variable); //undefined
},
variable:true
};
You don't have access to obj because this is bind to the instance of MyClass constructor - myClass. If in handler you want to have access to myClass through this and access to obj you have to use obj name directly so:
console.log(this); // myClass
console.log(obj.variable); // true
If you want to have this bind to obj use what Juan Mellado or gryzzly suggested.
How can I call PrintIt foo from Set()? I get error that it can't find it...
I know it's possible to call it via MyObject.prototype.PrintIt but this way i will "lose" the object and it's property (Num)
MyObject = function(){
this.Num=6;
}
MyObject.prototype = {
initialize: function(){
document.getElementById("button1").onclick = this.Set;
},
Set: function(){
this.PrintIt();
},
PrintIt: function(){
alert("I Print");
//alert( this.Num);
}
}
window.onload = function(){
obj = new MyObject;
obj.initialize();
}
The problem lies not in the prototype but in the way how you assign the method to the click handler. There it loses its connection to the object. You can use a closure:
initialize: function(){
var that = this;
document.getElementById("button1").onclick = function(){
that.Set();
};
},