No access to this in prototype - javascript

Why does this alert as undefined in the code below?
http://jsfiddle.net/7kwXd/6/
var testObj = {};
testObj.aMethod = function() {
this.testVar = "thing"
alert(this.anObject.dimension1);
alert(this.anObject.dimension2);
};
testObj.aMethod.prototype.anObject = {
dimension1 : this.testVar,
dimension2 : "thing2"
};
var testing = new testObj.aMethod();

You are creating an object ({dimension1: this.testVar, dimension2: "thing2"}) without any object context. What is this supposed to be at that time? After that, you are assigning it to testObj.aMethod.prototype.anObject.
You can use code like this to achieve what you want:
var testObj = {};
testObj.aMethod = function() {
this.testVar = "thing"
alert(this.anObject.dimension1);
alert(this.anObject.dimension2);
};
testObj.aMethod.prototype.getAnObject = function() {
return {
dimension1 : this.testVar,
dimension2 : "thing2"
};
};
var testing = new testObj.aMethod();
And then access that object with testing.getAnObject().dimension1.

Related

Copy object functions and properties in new object by value not by reference - javascript

I want to copy the functions and properties of an object into new object. The old object should not effect by changing made in new Object.
Here is the object definition:
var Call = function() {
this.number="123";
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
I can access function1 using callobj.function1().
What I have tried to copy it:
Javascript:
var newcallobj = Object.assign({}, callobj);
In this case, i am not able to access function1 but i can access number property directly.
JQUERY:
var newObj = jQuery.extend(true, {}, callobj); OR
var newObj = jQuery.extend({}, callobj);
In this case, i am able to access function1 and property but when i change number like that newObj.number="222". It also change the value of original object.
I know that there is couple of other posts. But all is not working for me. Please let me know if i am doing any thing wrong?
AFTER #gurvinder372 answer(I am updating question):
After #gurvinder372 answer. It is working for first level of property but if it has another object like i show below and i change the value of property of another object. Then it is effecting on original object also.
var ABC = function(){
this.number = "333";
}
var Call = function() {
this.number="123";
this.anotherobj = new ABC();
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
var newcallobj = Object.create(callobj);
newcallobj.anotherobj.number= "123";
console.log(newcallobj.anotherobj.number);
console.log(callobj.anotherobj.number);
Output of both is 123. #gurvinder372. can you check th above code ?
Object.assign only copies the enumerable properties of an object.
Use Object.create instead of Object.assign
var newcallobj = Object.create(callobj);
var Call = function() {
this.number="123";
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
var newcallobj = Object.create(callobj);
console.log(newcallobj.function1());
Ok. By the help of #gurvinder372. The following solution is working for me.
var ABC = function(){
this.number = "333";
}
var Call = function() {
this.number="123";
this.anotherobj = new ABC();
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
var newcallobj = Object.create(callobj);
newcallobj.anotherobj = Object.create(callobj.anotherobj);
newcallobj.anotherobj.number= "123";
console.log(newcallobj.anotherobj.number);
console.log(callobj.anotherobj.number);
Please let me know if there is any better solution other than this?

Javascript inheritance is not working

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();

How to change property of the object by event?

I have a constructor:
var Constructor = function(property) {
this.property = property;
this.changeProperty = function() {
*by clicking should change the property*
}
}
Then I create an object:
var newObject = new Constructor(propertyValue);
newObject.changeProperty();
So, is it possible to change the property value of the already created object?
So, is it possible to change the property value of the already created
object?
Yes, try
var Constructor = function(property) {
this.property = property;
var self = this;
this.changeProperty = function( newProperty ) {
self.property = newProperty;
}
}
And invoke it as
var newObject = new Constructor(propertyValue);
newObject.changeProperty(newPropertyValue);
var Constructor = function(property) {
this.property = property;
this.changeProperty = function(newProp) {
this.property = newProp
}
}
var newObject = new Constructor("oldProp");
newObject.property //oldPropery
newObject.property = "newproperty"
newObject.property//"newproperty"
You can also do it using getter and setter.The property is already public.

Extend the properties returned by a function?

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.

javascript private inner functions in module with access to "this" scope [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Javascript outer scope variable access
I have a javascript module that looks something like below. The main issue I'm having is how to access variables in the "this" scope from the private someOtherFunc. Is there a way to access this.myvar in the private someOtherFunc
var mymodule = (function(){
return {
MyObj : function() {
this.myvar = 123;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
//this doesn't seem to work
this.myvar = 456;
};
}
}
}
The idea is that I want to be able to do something like
new mymodule.MyObj().publicfunc, but make the someOtherFunc private
Forget my previous answer. You can do this just by adding a private version of this.
var mymodule = (function() {
return {
MyObj : function() {
this.myvar = 123;
var that = this;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
that.myvar = 456;
};
return this;
}
};
});
Bear in mind that, with your code, every time you call MyObj you get a new object.
So this would do what you want:
>var o = new mymodule().MyObj()
>o.myvar
123
>o.publicfunc()
>o.myvar
456
but not this
>var m = new mymodule()
>m.MyObj().myvar
123
>m.MyObj().publicfunc()
>m.MyObj().myvar
123
If that's not what you want, consider doing something like this
var mymodule = (function() {
var myObj = null;
this.MyObj = function() {
if(myObj != null)
return myObj;
myObj = {};
myObj.myvar = 123;
myObj.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
myObj.myvar = 456;
};
return myObj;
};
});
Declare myvar using the var keyword, making it private, then access it without the this.:
function MyObj(){
var myvar = 123;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function(){
alert(myvar);
};
}
var o = new MyObj();
o.publicfunc();
If you need public access to myvar then create a public getter/setter.
jsFiddle Demo
​
I think what you're looking for is a way to encapsulate myvar for changes. When some of the other answers run, myvar usually will stay as 123 because the initially returned object from mymodule holds on to that initial value.
Return a function that gets the value of myvar even after it's been modified, and I think that helps your problem.
Here's the code that works for me:
var mymodule = (function(){
var myvar = 123,
publicfunc = function() { myvar = 456 },
getMyVar = function() { return myvar; };
return {
someOtherFunc : publicfunc,
myPublicVar : getMyVar
};
}());
mymodule.someOtherFunc();
alert(mymodule.myPublicVar());​ //gives you 456
JSFiddle here.
I hope this helps.
Why not build it a little more deliberately?
// this one returns an object used like:
// myModule.myInt; /* 456 */
// myModule.myFunc(); /* 124 */
var myModule = (function () {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) { return num + 1; },
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
}());
I went through the trouble of explicitly naming the returned, public object, but it's now very clear what is and isn't public, and yet, each one of those things will have access to the variable versions of one another, with the one exception being that if you change myModule.myInt or publicData, they will no longer be equal.
To demonstrate what I mean in the comments below, creating multiple instances with their own private data/methods, I just add in one more layer of function-scope:
var myModule = (function () {
var static_int = 789,
makeInstance = function (/* any constructor values */) {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) {
console.log(static_int);
return num + 1;
},
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
};
return makeInstance;
}());
You now use it like:
var newModule = myModule(/* instance parameters */);
newModule.myFunc();
...or
var num = myModule(/* instance parameters */).myFunc();
If you wanted to save memory, you could have static helper functions inside of the static-layer:
var myModule = (function () {
var static_int = 789,
static_addOne = function (num) { return num + 1; },
static_divideBy = function (dividend, divisor) { return dividend/divisor; },
makeInstance = function (/* any constructor values */) {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) {
console.log(static_int);
return num + 1;
},
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
};
return makeInstance;
}());
And now you have "private" functions which are only written one time (ie: you save memory), but any instance can use those functions.
Here's the catch:
Because of how scope and closure work, the static functions have NO access to values inside of the instance (functions inside have access to the static functions, not the other way around).
So, any static helper functions MUST have the values passed to them as arguments, and if you're modifying a number or a string, you MUST return the value out of that function.
// inside of a private method, in any instance
var privateString = "Bob",
privateFunc = function () {
var string = static_helper(privateString);
privateString = string;
//...
};
You don't return anything from MyObj.
return this;
should fix it.
Use the bind method:
var someOtherFunc = function() {
this.myvar = 456;
}.bind(this);

Categories

Resources