When does it make sense to use function expressions instead of function declarations when implementing "private methods"? In both cases, the functions are encapsulated, the only practical difference appears to be that I wouldn't be able to call myFunc1 in the constructor. I know I should be using the prototype property either way, but I'm just curious.
function myClass
{
myFunc1() //error
myFunc2() //success
var myFunc1 = function()
{
}
function myFunc2()
{
}
}
You can call the function assigned to a variable, but you have to assign it before you can call it:
function myClass() {
var myFunc1 = function() {
}
myFunc1() //success
myFunc2() //success
function myFunc2() {
}
}
Those functions are local to the constructor, so it's not the same as using the prototype. To make a public function you need to assign it to the object:
function myClass() {
this.myPublicFunc1 = function() {
}
this.myPublicFunc2 = myFunc2;
function myFunc2() {
}
}
var o = new myClass();
o.myPublicFunc1() //success
o.myPublicFunc2() //success
You must use an expression if you want to invoke the function immediately.
This one invokes it and assigns the return value to the variable:
function myClass {
var myVar = function() {
return 'some value'; // <--- 2. assign the return value to the variable
}(); // <--- 1. invoke the function immediately
function myFunc2() {
}
}
This one invokes it, but assigns the function itself to the variable:
function myClass {
var myFunc1;
(myFunc1 = function() { // <--- 1. assign the function to the variable
// Do something
})(); // <--- 2. invoke the function immediately
function myFunc2() {
}
}
Related
I can store a function in a variable and call it later like this
var storedFunction = functionName;
//Later On
storedFunction(); //Equivalent to functionName()
How can I store a function like this and call it later, also executing this when its called so this would be the
var storedFunction = this.function1().function2();
Later I could call it like this and this would be the class.
class MyClass {
method() {
storedFunction();
}
}
If you have a function like this :
function myFunction(){
return {
function inner(){
return 'some data'
}
}
}
When you call myFunction with myFunction() returned value is an object like this:
{
inner: function (){ return 'some data'; }
}
If you want to store inner function just need store your value with it's key from returned object, like this:
let myInnerFunction = myFunction().inner;
...
//and when you want call that
myInnerFunction ()
In your case this is correct:
let storedFunction = this.function1().function2;
If you want to run function1 and function2 when you call there is a simple way:
let storedFunction = () => {
return this.function1().function2();
}
// or without arrow function
let storedFunction = function () {
return this.function1().function2();
}.bind(this)
The dot operator (.) is the object access operator. That means whenever you see it (not related to a number), the code is attempting to access a property or method (function) of that object.
That means: this.something is attempting to access the something property on an object referred to as this.
Related, then function1().function2() means function2() must be a method of an object too. But, in this case, the object must be returned from function1() in order for this to work.
So here is some sample code that would do what you expect.
function function1() {
return {
function2: () => {
console.log('called function2 from function1 on "this"');
}
}
}
function1.bind(this);
this.function1().function2();
// Using class syntax
class OtherClass {
function2() {
console.log('Used class keyword');
}
}
class MyClass {
constructor() {
this.veryOddThingToDo = this.function1().function2;
}
function1() {
return new OtherClass();
}
}
const myClass = new MyClass();
// Get reference to function2() from "MyClass.function1()" call
const oddness = myClass.veryOddThingToDo;
// This is exactly: this.function1().function2() referenced"
oddness();
I wrote this, but not work
Can javascript function pass self to other function
Can I also access the variable in the caller function?
function caller()
{
var variable=123;
calledfunction(this);
}
function calledfunction(caller)
{
console.log(caller.variable);
}
caller();
Change var variable in the assignment to this.variable:
function caller()
{
this.variable=123;
calledfunction(this);
}
function calledfunction(caller)
{
console.log(caller.variable);
}
caller();
In this case caller is not really generating a new instance/scope so this is actually global which is bad. It would be better to create a new empty object and use that to hold data instead of using this.
function caller()
{
var data = {};
data.variable=123;
calledfunction(data);
}
function calledfunction(values)
{
console.log(values.variable);
}
caller();
Alternatively you can use a closure in this case by putting calledfunction inside caller:
function caller()
{
var variable=123;
calledfunction();
function calledfunction()
{
console.log(variable);
}
}
caller();
I have following module
module.js
var Instance = (function () {
jsfunc('fn');
var fn = function () {
console.log('this in fn');
}
}());
jsfunc.js
function jsfunc(fn) {
// how to find if fn is defined in Instance module
}
As I am passing string, which is a function inside instance module. And then I want to check if that jsfunc's parameter function is defined inside Instance. How can I achieve this?
You need pass a function reference instead of a function name, since it is in a closure scope
var Instance = (function () {
var fn = function () {
console.log('this in fn');
}
jsfunc(fn);
}());
function jsfunc(fn) {
// how to find if fn is defined in Instance module
if (typeof fn == 'function') {
fn()
}
}
Demo: Fiddle
Also note that the value of Instance will be undefined since there is no value returned from the anonymous function.
why doesn't this work as expected. (see expected comment)
var Module = function () {
var public_instance_var;
function doStuff () {
Module.doOtherStuff();
console.log(public_instance_var); // expected: true, but logs undefined
};
function doOtherStuff() {
public_instance_var = true;
};
return {
public_instance_var: instance_var,
doStuff: doStuff,
doOtherStuff: doOtherStuff
}
}();
Module.doStuff();
Update: Fixed accordingly to a few of jAndy suggestions
Multiple errors here:
You don't return DoStuff as module interface
instance_var is not declared, probably meant public_instance_var
doOtherStuff is never assigned to Module, just call it like doOtherStuff();
Fixed code:
var Module = function () {
var public_instance_var;
function doStuff() {
doOtherStuff();
console.log(public_instance_var); // expected: true, but logs undefined
};
function doOtherStuff() {
public_instance_var = true;
};
return {
doStuff: doStuff,
public_instance_var: public_instance_var
}
}();
Module.doStuff();
change your code like so
var Module = function () {
var public_instance_var;
function doStuff () {
doOtherStuff();
console.log("var is ", public_instance_var); // expected: true, but logs undefined
};
function doOtherStuff() {
public_instance_var = true;
};
return {
public_instance_var: public_instance_var,
doStuff : doStuff
}
}();
Module.doStuff();
you have to return doStuff() function (otherwise outside it will be undefined) and public_instance_var instead of instance_var
you need to execute doOtherStuff() without prefixing Module.
What this code does is, simply put: create and run a function and assign its return value to a variable: Module. The return value is an object with 1 property: public_instance_var, that points to the variable instance_var, or (after correcting the typo: public_instance_var). This variable was declared, but not instantiated. Therefore the return value looks like this:
Module.public_instance_var = undefined
The very last line Module.doStuff(); won't work one bit: Module is an object that has no methods. The functions you declared are garbage collected when the anonymous function returns. If you want access to those functions, you'll need to include them in the return statement. Read up on closures, Object constructors and design patterns in general, but I'd say the code you're after will look something like this:
var Module = (function()
var public_instance_var;
function doStuff () {
this.doOtherStuff();
console.log(public_instance_var); // expected: true, but logs undefined
};
function doOtherStuff() {
public_instance_var = true;
};
return {
public_instance_var: public_instance_var,
doStuff: doStuff,
doOtherStuff: doOtherStuff
};
})();
Of course, this way your variable public_instance_var is a public property, so my guess would be what you're really trying to do is simulate a private properties and methods. In which case you might end up with code similar to this:
var Module = (function()
{
var public_instance_var;
return {
//public_instance_var: public_instance_var, remove this line
//the closure will preserve access to the variable
doStuff: function ()
{
this.doOtherStuff();//this, you're referencing the object's property
console.log('here I am');
},
doOtherStuff: function ()
{
public_instance_var = true;
//this won't work anymore:
//this.public_instance_var = true;
};
}
})();
Module.doStuff() now logs here I am, but the doOtherStuff is now a public method, too. Here's how you might choose to solve the issue:
var Module = (function()
{
var public_instance_var;
function doOtherStuff ()
{
public_instance_var = true;
};
return {
//public_instance_var: public_instance_var, remove this line
//the closure will preserve access to the variable
doStuff: function ()
{
doOtherStuff();//don't use this here, but the reference to the function exists thanks to closure
console.log('here I am');
console.log(public_instance_var);//logs true
}
};
})();
These are just a few of the very powerful things you can do with closures and functions returning objects. Just read a couple of articles, like this one, there are better ones out there. Google the term power constructors
I'd like to call functions I've defined within the document ready function of jQuery, but am having a bit of trouble. I have the following code:
jQuery(document).ready( function($) {
function test1() {
alert('test1');
}
function test2() {
alert('test2');
}
var test_call = '2';
var fn = 'test' + test_call;
// use fn to call test2
});
I don't want to use eval, and window[fn] doesn't seem to be working. The two test functions don't appear to be indices in the window variable. I appreciate the help and knowledge.
All I can think of that doesn't use eval() or some form of eval (passing a string to setTimeout() is a form of eval()), is to register the relevant function names on an object and then look up the function name on that object:
jQuery(document).ready( function($) {
function test1() {
alert('test1');
}
function test2() {
alert('test2');
}
// register functions on an object
var funcList = {};
funcList["test1"] = test1;
funcList["test2"] = test2;
var test_call = '2';
var fn = 'test' + test_call;
if (fn in funcList) {
funcList[fn]();
}
});
or the registration could be done in the definition of the functions. If they were global functions, they would be implicitly registered on the window object, but these are not global as they are scoped inside the document.ready handler function:
jQuery(document).ready( function($) {
var funcList = {};
funcList.test1 = function test1() {
alert('test1');
}
funcList.test2 = function test2() {
alert('test2');
}
var test_call = '2';
var fn = 'test' + test_call;
if (fn in funcList) {
funcList[fn]();
}
});
Or, you could move the functions to the global scope so they are automatically registered with the window object like this:
function test1() {
alert('test1');
}
function test2() {
alert('test2');
}
jQuery(document).ready( function($) {
var test_call = '2';
var fn = 'test' + test_call;
if (fn in window) {
window[fn]();
}
});
The best way, if not Eval, would be to use setTimeout with zero milliseconds, as you can specify the function as a string.
setTimeout('myfunction()',0,);