Facing inheritance problem in this below code i am new to OOPS concepts please help me.
var testA = function() {
this._data = undefined
};
testA.prototype.init = function(data) {
this._data = data;
};
testA.prototype.get = function(data) {
if (this._data) {
return data
}
};
var testB = function() {}
testB.prototype = Object.create(testA);
var instance = new testB();
testB.prototype.init = function(data) {
testA.prototype.init.call(this, data);
};
testB.prototype.Somedata = function() {
testA.prototype.get();
}
instance.init("testdata");
instance.Somedata() // here i am getting this._data is undefined
When i call instance.init("testdata") now it's setting value to this._data in the parent.
When i call instance.Somedata() here i am getting undefined
May i know what could be reason? and how can i get the this._data value when i call instance.Somedata().
At first:
testB.prototype = Object.create(testA);
Instantiates a function, you may want to either instantiate the prototype:
testB.prototype = Object.create(testA.prototype);
or construct it directly:
testB.prototype =new testA;
Secondly SomeData is not returning anything, may do so and you also need to keep the context:
testB.prototype.Somedata = function() {
return testA.prototype.get.call(this,"return");
}
Or even easier if we did the upper inheritance right:
testB.prototype.Somedata = function() {
return this.get("return");
}
Your using Object.create against a constructor, you should use it against an instance, otherwise, you get a function in return instead of an object.
var TestA = function() {
this._data = undefined;
};
TestA.prototype.init = function(data) {
this._data = data;
};
TestA.prototype.get = function() {
return this._data;
};
var instance = Object.create(new TestA());
instance.init('some');
instance.get();
Related
Hi I'm trying to implement a LinkedList in Javascript. When i assign a value to my node it doesn't seem to store it when I use my getter. For example:
var Node =function() {
var _data;
var _next ={};
var that = this;
that.getData = function() {
return _data;
};
that.setData = function(data) {
that._data = data;
};
that.getNext = function() {
return _next;
};
that.setNext = function(next) {
that._next = next;
};
return that;
};
Will not work with:
var nodeObj = new Node();
nodeObj.setData("hello");
console.log(nodeObj.getData());
_data is not the same as that._data, you must do this:
that.getData = function() {
return that._data;
};
OR you could do this instead:
that.setData = function(data) {
_data = data;
};
the benefit of the second approach being that you're simulating a private variable (because you cannot do nodeObj._data in the second case but you can in the first)
also var that = this; is unnecessary, you can simply do this._data in this case.
For your case here, you can assume that if you're calling a function like yourObject.someFunction(), then within someFunction the value of this equals yourObject. (And this isn't always true in javascript but since you're starting off you should think about it this way for now. If you pass a function to another function as a variable and then call it then this wouldn't be the case).
What is the best way to control if an object should not be created in Javascript? I have been searching, and it seems that the only way to not returning this, is returning an object. This does not work:
var Example = function( params ) {
if(!params){
return null;
}
};
var foo = new Example(); // foo is not null
I donĀ“t want foo to be instanceOf Example.
Thanks, best regards.
Basically you're creating an object using your function as a constructor but the return value from a constructor is ignored.
What you can do is make a factory function like so
http://javascript.info/tutorial/factory-constructor-pattern
Example = function()
{
this.Value = 10;
}
Example.Create = function(params ) {
if(!params){
return null;
}
return new Example();
}
var result = Example.Create();
alert(result);
jsFiddle here : https://jsfiddle.net/CanvasCode/3pab7cco/
Or you can add a bool value to your function and then check that after you have created your object
var Example = function( params ) {
this.isValid = true;
if(!params){
this.isValid = false;;
}
};
var example = new Example();
if(!example.isValid){ example = null; }
alert(example);
I'm a JS beginner. I have defined a function on my Backbone model as follows.
myFunction: function () {
return {
firstAttr: this.model.get('value-attribute')
};
}
It is available to me as this.myFunction.
From somewhere else in the code, I want to extend this.myFunction to return another attribute. In other words, I'd like it to return a dict with two attributes: { firstAttr: 'something', secondAttr: true }.
How can I do this?
I've tried:
this.myFunction().secondAttr = true;
but I know that's the wrong thing to do.
Assuming your model prototype looks like
var MyModel = Backbone.Model.extend({
myFunction: function () {
return {
// I assume you work directly on a model
// the principle would be the same with a wrapper object
firstAttr: this.get('value-attribute')
};
}
});
you can either mask your method on a model by model basis like this:
var m = new MyModel({'value-attribute': 'attr, the first'});
console.log(m.myFunction());
m.myFunction = function () {
var res = MyModel.prototype.myFunction.call(this);
res.secondAttr = true;
return res;
};
console.log(m.myFunction());
See http://jsfiddle.net/V8zt2/ for a demo
Or dynamically modify your prototype to alter all instances :
var f = MyModel.prototype.myFunction;
MyModel.prototype.myFunction = function () {
var res = f.call(this);
res.secondAttr = true;
return res;
};
var m = new MyModel({'value-attribute': 'attr, the first'});
console.log(m.myFunction());
http://jsfiddle.net/V8zt2/1/
How about modifying your myFunction to :
myFunction : function () {
var i,
obj = {};
for (i=0; i< arguments.length;i++){
obj['attribute'+(i+1)] = this.model.get(arguments[i]);
}
return obj;
}
This way you can send keys of model, that you want to be in the returned object as arguments to myFunction.
I have a Object based on some closure, and want to implement event scheme here:
var class1 = function(val1)
{
var val = val1;
//------ want to call a method of Object of class1--------
var self = this;
setTimeout(function()
{
self.onEvent();
}, 1000);
//----------------
return {
f1: function()
{
return val;
},
onEvent: function()
{
console.log('not implemented yet. Override');
}
};
};
var obj1 = class1(5);
console.log(obj1.f1()); //5
obj1.onEvent(); //not implemented yet. Override
obj1.onEvent = function()
{
console.log('event fired');
}
got error, and I know the reason, and I need a solution:
5
not implemented yet. Override
/....../app.js:9
self.onEvent();
^
TypeError: Object #<Object> has no method 'onEvent'
It is possible if this bind with addEventListener scheme like this:
(The idea based on
Implementing events in my own object
)
var class2 = function()
{
var _this = this;
_this.events = {};
var fireEvent = function(name, args)
{
if (!_this.events.hasOwnProperty(name)) return;
if (!args || !args.length) args = [];
var evs = _this.events[name];
var l = evs.length;
for (var i = 0; i < l; i++)
{
evs[i].apply(null, args);
}
};
setTimeout(function()
{
fireEvent('testEvent', ['hello'])
}, 1000);
return {
addEventListener: function(name, handler)
{
if (_this.events.hasOwnProperty(name))
_this.events[name].push(handler);
else
_this.events[name] = [handler];
}
};
};
var obj2 = class2();
obj2.addEventListener('testEvent',
function(data)
{
console.log('event fired: ' + data);
});
event fired: hello
However, I prefer not to use addEventListener but .onEvent() scheme.
Is it possible? Perhaps it is possible using call/apply.
Thanks for your advice.
In your first block of code, you are returning an object, which is different from this or self.
You don't necessarily have to return this in your constructors but you should assign your functions on the returned object. If you create a variable for the object you want to return, you can use it in your setTimeout callback like so:
var class1 = function(val1)
{
var val = val1;
var obj = {
f1: function()
{
return val;
},
onEvent: function()
{
console.log('not implemented yet. Override');
}
};
setTimeout(function()
{
obj.onEvent();
}, 1000);
return obj;
};
For extra style points, you might want to capitalize the name of your constructors (and perhaps use new to instantiate them to make things clearer to your readers).
How could I do this?
Class
var Factory = (function() {
var Class = function() {
this.name = 'John';
this.methods = {
get: function(callback) {
callback();
}
};
};
return {
createClass: function() {
return new Class();
}
};
}());
Usage
var MyClass = Factory.createClass();
MyClass.methods.get(function() {
this.name // => returns undenfined
});
Thanks for any help!
You need to save a reference to this in the outer Class function and call call:
var instance = this;
this.methods = {
get: function(callback) {
callback.call(instance);
}
};
var Class = function() {
// Save a reference to this that can be used in local closures.
var me = this;
this.name = 'John';
this.methods = {
get: function(callback) {
// Use 'call()', passing the reference to the 'Class' object
callback.call(me);
}
};
};
#SLaks - The declaration of scope as a Global variable is bad practice.
#Ferdinand Beyer - have you tested if it functions?
The better way will be the scope binding. The Prototype javascript framework produced a nice concept and we can easily implement it like
Function.prototype.bind = function(scope) {
var _function = this;
return function() {
return _function.apply(scope, arguments);
}
}
and then yoou code should have only a single change and it will maintin the scope of your class.
var Factory = (function() {
var Class = function() {
this.name = 'John';
var me = this;
this.methods = {
get: function(callback) {
callback();
}
};
};
return {
createClass: function() {
return new Class();
}
};
}());
var MyClass = Factory.createClass();
MyClass.methods.get(function() {
console.info(this.name) // => returns undenfined
}.bind(MyClass));
I mean only the function call get with .bind(MyClass)