How to access from 'private method' to 'public variable', in Javascript class - javascript

First, See my code plz.
function test(){
this.item = 'string';
this.exec = function(){
something();
}
function something(){
console.log(this.item);
console.log('string');
}
}
And I made class and call 'exec function', like this code
var t = new test();
t.exec();
But result is...
undefined
string
I wanna access from something function to test.item.
Have you any solution?

You need to call something with apply so that this is properly set inside of something:
function test(){
this.item = 'string';
this.exec = function(){
something.apply(this);
}
function something(){
console.log(this.item);
console.log('string');
}
}
As #aaronfay pointed out, this happens because this doesn't refer to the object that new test() created. You can read more about it here, but the general rule is:
If a function is invoked on an object, then this refers to that object. If a function is invoked on its own (as is the case in your code), then this refers to the global object, which in the browser is window.

You have many choices, but I recommend the last one.
var item = 'string'
or
this.exec = function(){
something.apply(this, []);
}
or
var that = this;
function something(){
console.log(that.item);
console.log('string');
}

this.item in something() isn't what you think it is.
The this value is different. In this case, it's the global object.
The best solution, in my opinion, is to declare a variable with a reference to this, that can be accessed inside the inner function.
function test() {
var that = this; // a reference to 'this'
function something() {
console.log(that.item); // using the outer 'this'
console.log('string');
}
this.item = 'string';
this.exec = function(){
something();
}
}

Why not just define something like this:
Fiddle
function test(){
this.item = 'string';
this.exec = function(){
this.something();
}
this.something = function(){
console.log(this.item);
console.log('string');
}
}
var t = new test();
t.exec();
// output:
// string
// string

Related

Javascript Difference between normal function and function object

In Javascript, the way to create classes (or objects) is to use;
function MyObj()
{
this.someVar = "xyz";
this.someMethod = function(){}
}
My simple question is how different is this function from a normal JavaScript function...say a function which adds 2 numbers?
The function aren't different. What makes the difference is how you call them.
For example, those have the same effect :
function MyObj(){
this.someVar = "xyz";
this.someMethod = function(){
console.log(this.someVar);
}
}
var obj = new MyObj();
obj.someMethod();
and
function someMethod(){
console.log(this.someVar);
}
function MyObj(){
this.someVar = "xyz";
}
var obj = new MyObj();
someMethod.call(obj);
and
function someMethod(){
console.log(this.someVar);
}
function MyObj(){
this.someVar = "xyz";
}
var obj = new MyObj();
obj.f = someMethod;
obj.f();
As you tagged your question prototypal-inheritance, I'll complete by saying the best way to build your function would have been this one :
function MyObj(){
this.someVar = "xyz";
}
MyObj.prototype.someMethod = function(){
console.log(this.someVar);
}
var obj = new MyObj();
obj.someMethod();
This way, all instances of MyObj share the same function and thus are lighter.
The difference is not so much in the contents of the function, but in how you call it.
If you call var myObj = new MyObj() then a new object is created. By convention functions intended for use like this start with a capital letter.
If you were to call the function without the new keyword then exactly the same things happen inside the function, except that this will be the global object instead of the newly created object. This wouldn't matter in a simple "add 2 numbers" function, but can cause very odd bugs if you forget it.
One way to ensure that it doesn't matter if you forget the new call is to put this in the top of your function:
function MyObj() {
if (! (this instanceof MyObj)) {
return new MyObj();
}
...
}
None. What matters is the use of the new keyword.
See here:
function Fun(){
this.method = function(){
return "Bar";
}
return "Foo";
}
var value = Fun(); // assigns the return value of Fun() to value
alert(value); // "Foo"
// alert(value.method()); // won't work because "Foo".method doesn't exist
var instance = new Fun(); // assigns a new instance of Fun() to instance
alert(instance); // [object Object]
alert(instance.method()); // "Bar"

How to call a prototype function inside another prototype function without losing context

I have this CODE:
var MyObj = (function() {
//Constructor
var MyObj= function(){
this.myArray = [1,2,3];
}
MyObj.prototype = {
myFunc: function(){
alert(this.myArray.toString());
},
myFuncCaller: function(){
MyObj.prototype.myFunc();
}
};
return MyObj;
})();
var myObj = new MyObj();
myObj.myFunc();
//This line will throw an exception because this.myArray is undefined
myObj.myFuncCaller();
​
Why is this.myArray undefined?
I know I'm doing something wrong, how would be the correct way to do it?
Just use this:
this.myFunc();
When you call a function in Javascript, this is set to the expression you called it on.
In your code, for example, this in myFunc() is MyObj.prototype.

JS: Passing a scope as argument, binding it to a function that will be returned

Is it possible to define a function in the scope of a parent function and bind an argument passed through the parent function as its scope before returning it?
Here is an example:
var myObject = {
foo: "bar"
};
var myFunction = (function() {
return function() {
return this.foo;
};
}).call(myObject);
myFunction.call(myObject); // I'd like to bind myObject as this does ...
myFunction(); // ... but I'd like to do it before invoking it, without .call() or .apply()
Or another complex example, that describes what I'm trying to do:
var createMyCopy = function(original, self) {
var copy;
eval("copy=" + original.toString());
console.log(copy()); // returns undefined
};
(function() {
var self = "Hello world",
myFunction = function() {
return self;
};
console.log(myFunction()); // returns "Hello world"
createMyCopy(myFunction);
})();
I'm trying to create a copy of a function, so that I can make changes to it without changing the original one, but I'd like to have the variables that are defined in the original one in the copy as well...
Do you mean like this?
var myObject = {
foo: "bar"
};
var myFunction = (function() {
var self = this;
return function() {
return self.foo;
};
}).call(myObject);
I think you're getting scope and context mixed up in your question.
I think you mean this:
var myFunction = (function(obj) {
return function() {
return obj.foo;
};
})(myObject);
The immediately invoked function expression is passed myObject and returns a new function in which that parameter is bound as the variable obj.
I'm not sure what you mean, but you can do this:
var myObject = {
foo: "bar"
};
function myFunction() {
return this.foo;
}
console.log(myFunction.apply(myObject)); // bar
The first argument of apply is the context (ie. what this refers to). The second argument of apply is an array of arguments (but I've omitted that here as there are no arguments).

How to call a sibling method in an object defined with object syntax?

How to do this?
var obj = {
func1 : function(){
// Do stuff
},
func2 : function(){
func1(); // does not work
this.func1(); // does not work
}
}
Edit: missed a semicolon
var obj = {
func1 : function(){
// Do stuff
},
func2 : function(){
obj.func1(); // It works fine
}
}
if you want to use the 'this' keyword, you should do something like
function obj() {
this.param = whatever;
}
obj.prototype.method1 = function(){
...
}
obj.prototype.method2 = function(){
this.method1();
}
you could declare the methods in the obj function, but it is better to use prototype, because it is more efficient -- no matter how many obj instances you create, the functions only exist once. If you put the functions in the obj constructor, each instance of obj has its own copy of the function. javascript does some magic to associate the method call with the object instance on which it is called, to make sure 'this' means the right thing in context
I don't know why the person asking the original question thought that wouldn't work. Their example does work.
var obj = {
func1 : function(){
console.log("doing stuff");
},
func2 : function(){
this.func1(); // works fine!
}
}
You can paste that into the console and call obj.func2() and it works just fine. You don't need to name the object in this situation.
But be careful. This solution wouldn't work if you define another anonymous function inside of func2, and then try to use "this" inside of that function (such as if you're defining a callback). You'll get a "Uncaught TypeError: this.func1 is not a function" error. The problem in that situation is that "this" no longer refers to the outer object, it now refers to the context of that new inner function. For example:
var obj = {
func1 : function(){
console.log("doing stuff");
},
func2 : function(){
var func3 = function () {
this.func1(); // doesn't work ("this" is no longer obj)
}
func3();
}
}
To fix that issue, you could save a local copy of "this". Example:
var obj = {
func1 : function(){
console.log("doing stuff");
},
func2 : function(){
var ourThis = this;
var func3 = function () {
ourThis.func1(); // works fine!
}
func3();
}
}
Another way is to create your object through a factory function. That way, you can initialize your functions and use them inside the others.
const objFactory = () => {
const func1 = () => {
// Do stuff
}
const func2 = () => {
func1(); // This will work
}
return { func1, func2 }
}
const obj = objFactory();
obj.func1();
obj.func2();

Javascript: How to get a reference to the parent object when "this" has been overwritten with "call"?

Okay, I'm hating Javascript right now, and I hope someone can help me.
I have code which is set up like the following:
function Obj1() {
var me = this;
this.something = "yay";
this.getThis = function(){
return me;
}
}
Obj1.prototype.method = function() {
return this.something;
};
function Obj2() {
this.something = "nay";
}
Obj2.prototype.method = function() {
return this.something;
};
var o1 = new Obj1();
var o2 = new Obj2();
document.write(o1.method()); // Returns yay
document.write(o1.method.call(o2)); // Returns nay, but I need "yay" here
(JSFiddle # http://jsfiddle.net/A9u9K/)
My Problem is, that I need to call Obj1.method in the second case, but I am absolutely unable to get a reference to the object :(
How can I work around this?
Edit: Sorry, I got my example code pretty wrong :( Updated it. I took most of the code from a previous answer, because it is much nicer and still illustrates my problem.
Updated Answer:
document.write(o1.method.call(o2)); // Returns nay, but I need "yay" here
You've said you've got it sorted now, but as the answer to that isn't actually shown here on SO, I figured I may as well update to show it.
If it's method you want to have access me, even if it's been called with a different this value, you have to define it like getThis, as a closure over me:
function Obj1() {
var me = this;
this.something = "yay";
this.method = function() {
return me.something;
};
this.getThis = function(){
return me;
};
}
function Obj2() {
this.something = "nay";
}
Obj2.prototype.method = function() {
return this.something;
};
...or of course, if you don't need the "something" to be a property on the object, just make it a var within the constructor (a private variable, like me):
function Obj1() {
var me = this;
var something = "yay";
this.method = function() {
return something;
};
this.getThis = function(){
return me;
};
}
function Obj2() {
this.something = "nay";
}
Obj2.prototype.method = function() {
return this.something;
};
Original Answer: (To Revision 1 of the question, which didn't have me.)
but I thought that, when creating a closure (as I do in 4) Javascript should preserve "this".
this is set entirely by how a function is called, not where it's defined; more about that here and here. But the way you've defined your getThis function, you can use the fact it closes over the constructor call to solve this (no pun) without using this:
function Obj1() {
var me = this; // <== Use a variable to remember `this`
this.something = "yay";
this.method = function() {
return this.something;
};
this.getThis = function(){
return me; // <== Return it
};
}
Live example
More about closures and the plumbing that makes the me thing work here.
There is a cost involved in this, and just generally in your pattern of defining functions within the constructor function: Each individual object created by Obj1 and Obj2 gets its own copy of each function. This can have memory implications if there are lots of these objects running around (but unless you have lots, you needn't worry and you get benefits like the me thing and other private variables). In constrast, if you use a function assigned to the prototype, all instances will share a single, common copy of the function.
In your sample code, only the getThis function really needs to be duplicated for every instance (because you're relying on the closure), so you can do this to avoid unnecessary function proliferation:
function Obj1() {
var me = this;
this.something = "yay";
this.getThis = function(){
return me;
};
}
Obj1.prototype.method = function() {
return this.something;
};
function Obj2() {
this.something = "nay";
}
Obj2.prototype.method = function() {
return this.something;
};
see it here http://jsfiddle.net/2Jhwv/5/
The issue is with the reference changing for the this object with scope.
Instead if using a this directly in closure use a local variable equated to this, i.e, change your Obj1 toL
function Obj1() {
this.something = "yay";
var that = this;
this.method = function() {
return that.something;
}
this.getThis = function(){
return that;
}
}
The only way to solve this is to another place holder to hold the value of this in Obj1 and use it in the function method() and getThis().
function Obj1() {
var instance = this;
this.something = "yay";
this.method = function() {
return instance.something;
}
this.getThis = function(){
return instance;
}
}
But what I cannot under stand is why you are doing it(obj1.getThis.call(obj2).method())?
This explicitly says that you want to change the scope of the method getThis() to something else, then you are trying to solve the problem which was created by this usage.
Can you tell why you want something like this?

Categories

Resources