In the js code specified below -
var tclass = function(){
this.func2=function(){console.log('func2')};
this.b={
func1: function(){console.log('func1')}
}
}
how do i call func2 inside func1 on the same instance?
You'd have to keep a reference to both this and that function in the closure.
var tclass = function(){
var obj = this;
function func2(){console.log('func2')};
this.func2 = func2;
this.b={
func1: function(){ obj.func2(); }
}
}
Also it's more useful to declare functions with actual function declaration statements:
function tclass() {
// ...
}
Related
I have an anonymous function inside a variable GLOBAL.
var GLOBAL = function (){
var func1 = function(){
console.log("function 1 go!")
}
var func2 = function(){
console.log("function 2 go!")
}
return {
init: function(){
func1();
}
}
}()
In my init function return func1, calling it so GLOBAL.init();.
My question is: how I can call functions directly for example GLOBAL.func1() or GLOBAL.func2().
You have to return the function references,
var GLOBAL = function (){
var func1 = function(){
console.log("function 1 go!");
}
var func2 = function(){
console.log("function 2 go!")
}
return { func1,func2 };
}();
Now you can access it like GLOBAL.func1() and GLOBAL.func2(). And do not confuse with the syntax { func1,func2 };. That is quite similar to { func1 : func1,func2 : func2 }; I just used the shorthand introduced in ES6.
You can't. They are locally scoped variables. Being inaccessible outside the function is a large part of the point.
If you want them to be accessible, then you need to make them so explicitly (as you have done for the anonymous function you assign to init).
You should explicit add those functions in the returned object. In this code you can still continue executing init() as a object initialization.
var GLOBAL = function (){
var func1 = function(){
console.log("function 1 go!")
};
var func2 = function(){
console.log("function 2 go!")
}
return {
init: function(){
this.func1();
},
func1,
func2
}
}();
GLOBAL.func1();
GLOBAL.func2();
I hope that helps :D
You can follow modular approach if it can help:
var GLOBAL = {
func1: function(){
console.log("function 1 go!")
},
func2: function(){
console.log("function 2 go!")
}
}
GLOBAL.func1();
GLOBAL.func2();
Say I have a given global IIFE closure
var foo = function(){
var x;
function doStuffToX(){
...
}
return { doStuff: doStuffToX }
}();
where x would be a reference to a DOM element.
Which of the below methods would be more efficient, given that there are 30+ of these DOM references, and foo.doStuff() would be rarely-sometimes invoked? Note that this would be a one-page app and therefore memory would not be cleared out.
Storing a reference to #x in foo.x
$(function(){
foo.init();
foo.doStuff();
});
var foo = function(){
var x;
function init(){
x = $('#x');
}
function doStuffToX(){
...
x.modifyDom();
...
}
return { init: init, doStuff: doStuffToX }
}();
Querying for #x in doStuff()s closure
$(function(){
foo.doStuff();
});
var foo = function(){
function doStuffToX(){
...
var x = $('#x');
x.modifyDom();
...
}
return { doStuff: doStuffToX }
}();
I have an object with two different sets of objects inside:
var myObj;
(function (myObj) {
var myFunction = (function () {
function myFunction(){
this.myValue = "something";
}
myFunction.getValue = function () {
var _this = this;
return _this.myValue;
}
return myFunction;
})();
myObj.myFunction = myFunction;
var myFunction2 = (function () {
function myFunction2() {
}
myFunction2.prototype.something = function () {
var a = myFunction.getValue();
}
return myFunction2;
})();
myObj.myFunction2 = myFunction2;
})(myObj || (myObj = {}));
Every time I run myFunction2.something(), a is assigned: undefined.
How can I get the value from myFunction into myFunction2.something()?
There is quite a mixup of scopes and design patterns in your code. Having 2 functions named the same way on inside the other creates different scopes for that name depending on where you call them. This quickly gets out of control. Like in this part:
var myFunction = (function () { // this guy is named myFunction
function myFunction(){ // this guy is also named myFunction
this.myValue = "something"; // 'this' here most certainly refers to 'window', not myFunction. Unless you do a 'new myFunction()' a la prototype
}
myFunction.getValue = function () {
var _this = this;// same here
return _this.myValue;
}
return myFunction;// here you are returning a function, not an object with methods
})();
Also I noticed that you are handling some logic with prototypes and other with closures, this also is kinda confusing when someone else (or you in a couple of months) need to refactor this code.
myFunction.getValue = function () {
var _this = this;
return _this.myValue;
}
return myFunction;
You could go all prototypes or all closures. I prefer closures so here is what I would do.
var myObj;
(function (myObj) {
// in this closure, we create a scope and return only the public methods
var myFunction = (function () {
// define properties here
var myValue = 'default value';
// define your methods, here we return
// myValue declared on the parent scope
function getValue() {
return myValue;
}
// this acts as a constructor, it autoexecutes
(function init(){
myValue = "something";
})();
// return all the functions in this scope
// you want to expose
return {
getValue: getValue
};
})();
// we then put myFunction into myObj
// at this point myFunction is an object with a method called getValue()
myObj.myFunction = myFunction;
var myFunction2 = (function () {
function something() {
// once this guy is called, we get the value from the other 'class'
var a = myFunction.getValue();
alert(a);// voila!
}
(function myFunction2() {
// do your init stuff here
})();
return {
something: something
};
})();
myObj.myFunction2 = myFunction2;
})(myObj || (myObj = {}));
// at this point myObj is an object with 2 'classes', each 'class' has its own methods
// we can proceed and call the desired method
myObj.myFunction2.something();
Demo: http://jsfiddle.net/bzw9kse7/
I've stepped through your code and just noticed a couple small things you're doing wrong.
You appear to be misdefining myFunction slightly, because it's not going to have myValue as a member variable, just a temporary variable that quickly falls out of scope. (And because it becomes undefined, it gets assigned to a, which is then unassigned).
So, replace these lines:
var myFunction = (function () {
function myFunction(){
var myValue = "something";
}
myFunction.getValue = function () {
var _this = this;
return _this.myValue;
}
return myFunction;
})();
With this:
var myFunction = (function () {
var myFunction = {};
myFunction.myValue = "something";
myFunction.getValue = function () {
var _this = this;
return _this.myValue;
}
return myFunction;
})();
EDIT Sorry, got this all wrong. It returns undefined because getValue is a static method of myFunction Object, not an instance method. That means that the this is not the same as in myFunction constructor.
Moreover you are not even attaching myValue to the this anywhere...
Edit 2 I added getMyValue to the myFunction prototype.
Try this:
....
var myFunction = (function () {
function myFunction(){
this.myValue = "something";
}
myFunction.prototype.getValue = function () {
return this.myValue;
}
// this creates the instance of the myFunction class.
return new myFunction();
})();
myObj.myFunction = myFunction;
...
// now you should be able to see the right result
var a = myFunction.getValue();
This is one of the craziest code I have ever seen, but the answer is this:
var a = myFunction.getValue(); is undefined because your 2nd definition of myFunction returns undefined, as in here:
function myFunction(){
var myValue = "something";
}
Your 2nd definition of myFunction actually replaces the 1st. See the comments below:
var myFunction = (function () {
// this definition replaces the one above
function myFunction(){
var myValue = "something";
}
myFunction.getValue = function () {
var _this = this;
return _this.myValue;
}
// which makes this return to not be taking in account when you are
// calling myFunction()
return myFunction;
})();
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
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();