How would I do the following:
var Parent = function() {
this.Child = {
childFunction: function() {
this.parentFunction();
}
};
this.parentFunction = function() {
}
};
var parentObj = new Parent();
parentObj.Child.childFunction();
At the moment I'm getting "undefined is not a function" because obviously parentFunction() isn't in scope, but I'm not sure what the best way to make it accessible is?
As this in Child will refer to Child object not Parent thus Store the reference of this of Parent in a variable which can be used later in childFunction.
var Parent = function() {
var _self = this; //Store the reference
this.Child = {
childFunction: function() {
_self.parentFunction(); //Use here
}
};
this.parentFunction = function() {
alert('In parentFunction');
}
};
var parentObj = new Parent();
parentObj.Child.childFunction();
var Parent = function() {
this.Child = {
childFunction: function() {
this.parentFunction();
}
};
this.parentFunction = function() {
}
};
Now inside this.Child childFunction this will refer to Child object and not the Parent.
So you must use self/that to refer to the parent.
var Parent = function() {
var that = this;
this.Child = {
childFunction: function() {
that.parentFunction();
}
};
this.parentFunction = function() {
}
};
You can just use Parent.parentFunction() as well.
var Parent = function() {
this.Child = {
childFunction: function() {
Parent.parentFunction();
}
};
this.parentFunction = function() {
}
};
The problem is that this in your childFunction refers to the current object which is Child.
The common solution would be to access the parent using a variable that is available through a closure. For example:
var Parent = function() {
var _this = this;
this.Child = {
childFunction: function() {
_this.parentFunction();
}
};
this.parentFunction = function() {
// ...
}
};
Alternatively, a more cumbersome approach would be to use bind to 'tie' the function context of the childFunction to the current this (which is the parent):
childFunction: function() {
this.parentFunction();
}.bind(this);
See MDN
Related
We are using a oop architecture as the following, and we have a scope problem. We have the 'self' variable for saving the context, but when we call the function 'print' in the overridden class, we are using the 'self' variable instead of 'this', and we cannot override a base method.
Do someone knows how override this methods with this architecture?
var baseItem = function() {
var self = {};
self.a = function () {
console.log('base');
return 1;
};
self.print = function() {
return self.a();
}
return self;
};
var middleItem = function () {
var parent = baseItem();
var self = Object.create(parent);
return self;
}
var overrided = function () {
var parent = middleItem();
var self = Object.create(parent);
self.a = function() {
console.log('overrided');
return 55;
};
return self;
}
var obj = overrided();
overrided.print(); // This returns 1 instead 55, as we would want
It's easy to make private variables accessed by public methods of a module you're exporting:
var makeAModule = function() {
var _secret = 'Ssh!';
var module = {
tellMeYourSecret: function() {
console.log(_secret);
}
};
return module;
}
// > var m = makeAModule();
// > m.tellMeYourSecret();
// Ssh!
Sometimes I need to define properties with Object.defineProperty that are computed by getters using the value of other private variables. Those have to go on an object, though, so I end up making a private object just to hold them. If I don't store all my private members on that object, it gets confusing to remember which props are on it and which aren't, so I put everything there:
var makeAModule = function() {
var priv = {};
priv._secret = 'Ssh!';
Object.defineProperty(priv, 'secretLength', {
get: function() {
return priv._secret.length;
}
});
var module = {
tellMeYourSecret: function() {
console.log(priv._secret);
},
howLongIsYourSecret: function() {
console.log(priv._secretLength);
}
}
return module;
}
// > var m = makeAModule();
// > m.howLongIsYourSecret();
// 4
Is there any way to define a variable (not attached to an object) whose value is computed through a getter? Something like this:
var makeAModule = function() {
var _secret = 'Ssh!';
Object.defineVariable('_secretLength', {
get: function() {
return _secret.length;
}
})
var module = {
tellMeYourSecret: function() {
console.log(_secret);
},
howLongIsYourSecret: function() {
console.log(_secretLength);
}
}
return module;
}
Not directly.
However, you can set it as a property of window, thus making it a global variable. But using global variables is not recommendable, specially if they are secret.
var makeAModule = function() {
var priv = {};
priv._secret = 'Ssh!';
Object.defineProperty(window, '_secretLength', {
get: function() {
return priv._secret.length;
}
});
return {
tellMeYourSecret: function() {
return _secret;
},
howLongIsYourSecret: function() {
return _secretLength;
}
};
};
document.body.innerHTML =
"Secret length: " + makeAModule().howLongIsYourSecret();
Alternatively, you can define your getters as properties of an object, and use a with statement. Note that the with statement can't be used in strict mode.
var makeAModule = function() {
var priv = {};
priv._secret = 'Ssh!';
Object.defineProperty(priv, '_secretLength', {
get: function() {
return priv._secret.length;
}
});
with(priv) {
return {
tellMeYourSecret: function() {
return _secret;
},
howLongIsYourSecret: function() {
return _secretLength;
}
};
}
};
document.body.innerHTML =
"Secret length: " + makeAModule().howLongIsYourSecret();
In the BusMonitor object, "this" refers to window object thats why "name" property become global for entire script when I call BaseFunction.call(this) on BusMonitor object. I just want the BaseFunction's properties only available to BusMonitor object. How to do that ?
function BaseFunction() {
this.name = "test";
}
var BusMonitor = function () {
BaseFunction.call(this);
return {
init: function () {
}
}
}();
I can do it by the way below but I dont want to create object like this.
function BusMonitor () {
BaseFunction.call(this);
return {
init: function () {
}
}
};
var busMonitor = new BusMonitor();
busMonitor.init();
You can, if it's possible of course, create object first and then pass it to BaseFunction
function BaseFunction() {
this.name = "test";
}
var BusMonitor = function () {
var obj = {
init: function () { }
};
BaseFunction.call(obj);
return obj;
}();
You can define a localScope in BusMonitor to hold name value, like this:
function BaseFunction() {
this.name = "test";
}
var BusMonitor = function () {
var localScope = {};
BaseFunction.call(localScope);
console.log("local name:" + localScope.name);
return {
init: function () {
}
}
}();
console.log("global name: " + name);
I tried to call from child object a parent attribute
var parentObj = {
attr1:1,
attr2:2,
childObj:{
method1:function(){
return this.attr1 * this.attr2;
}
}
}
but it doesn't work.
Try referencing parentObj directly:
var parentObj = {
attr1: 1,
attr2: 2,
childObj: {
method1: function () {
return parentObj.attr1 * parentObj.attr2;
}
}
}
This can be done with the power of closures!
var Construct = function() {
var self = this;
this.attr1 = 1;
this.attr2 = 2;
this.childObj = {
method1: function () {
return self.attr1 * self.attr2
}
}
}
var obj = new Construct();
var parentObj = {
attr1:1,
attr2:2,
childObj:{
method1:function(){
return this.parent.attr1 * this.parent.attr2;
}
},
init:function(){
this.childObj.parent = this;
delete this.init;
return this;
}
}.init();
This is an another approach without referencing the parent object's name.
var parentObj = {
attr1: 1,
attr2: 2,
get childObj() {
var self = this;
return {
method1: function () {
return self.attr1 * self.attr2;
}
}
}
}
Can be accessed as:
parentObj.childObj.method1(); // returns 2
There is a problem with referencing parent object my name because it breaks the app in case you rename it. Here is nicer approach, which I use extensively, where you pass the parent as an argument to the child init method:
var App = {
init: function(){
this.gallery.init(this);
},
somevar : 'Some Var'
}
App.gallery = {
init: function(parObj){
this.parent = parObj;
console.log( this.parent.somevar );
}
}
App.init();
Unsure if I've phrased this correctly, but in the callback how do I reference the controls property of the base class?
This has been bugging me for some time and I usually work around it, but I'd be grateful if anybody can enlighten me on how I should do this properly.
var base = function() {
var controls = {};
return {
init: function(c) {
this.controls = c
},
foo: function(args) {
this.init(args.controls);
$(this.controls.DropDown).change(function() {
$(this.controls.PlaceHolder).toggle();
});
}
}
};
Much Obliged,
Paul
Use the power of closures:
var base = function() {
var controls = {};
return {
init: function(c) {
this.controls = c
},
foo: function(args) {
var self = this;
this.init(args.controls);
$(this.controls.DropDown).change(function() {
$(self.controls.PlaceHolder).toggle();
});
}
}
};
Although closures are preferred, you could also use jquery bind to pass an object along:
var base = function() {
var controls = {};
return {
init: function(c) {
this.controls = c
},
foo: function(args) {
this.init(args.controls);
$(this.controls.DropDown).bind('change', {controls: this.controls}, function(event) {
$(event.data.controls.PlaceHolder).toggle();
});
}
}
};
You need to leverage closures here.
var base = function() {
var controls = {};
return {
init: function(c) {
this.controls = c
},
foo: function(args) {
this.init(args.controls);
$(this.controls.DropDown).change(function(controls) {
return function(){
$(controls.PlaceHolder).toggle();
}
}(this.controls));
}
}
};