In javascript, I have an object containing a function and want to add to it a private member.
How can I do that?
function function1 () {
var function2 = function () {
console.log("This is an actual function.");
}
function2.publicMember = 5;
function2.privateMember = 7;
return function2;
}
I want privatMember to be inaccessible to the user of function1.
I found this question but I can't quite translate it to my situation because my object is a function:
How to add private variable to this Javascript object literal snippet?
thanks!
Wrap it into one more function to create new scope (i.e. using iife):
function function1 () {
var function2 = (function(){
var privateMember = 7;
return function () {
privateMember ++; // do something with really private member
console.log("This is an actual function.");
}
})();
function2.publicMember = 5;
return function2;
}
Declare the vars inside the function that needs access to them:
function function1 () {
var publicMember = 5;
var function2 = function () {
var privateMember = 7;
console.log("This is an actual function.");
}
return function2;
}
So function2 can see the vars inside its own closure (privateMember) and any parent scope.
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();
Calling getFunction will return a unique function every time, right?
var getFunction = function() {
var myFunction = function() {
};
return myFunction;
}
var function1 = getFunction();
var function2 = getFunction();
function1 === function2; // false
Yes, every time a function is called, a new scope is created for that run and all variables defined in it are unique and not shared between runs of the function.
Even doing something like the following would have the same result as the inner function is still defined inside of the function's scope and can see the arguments to the outer function.
var getFunction = function() {
function myFunction() {
};
return myFunction;
}
var function1 = getFunction();
var function2 = getFunction();
function1 === function2; // false
This can be visualized as follows. The outer scope holds the three variable allocations and the getFunction invocations will create two new scopes which return a function object defined in that scope.
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;
})();
I try to figure out, how closure works, this is my example
function func1(func) {
return function(summand) {
return func() + summand;
}
}
var func2 = function() {
return 3;
}
var func3 = func1(func2);
var value = func3(4);
alert(value);
var func2 = function() {
return 100;
}
var newValue = func3(100);
alert(newValue);
First of all let breaks down the code. I write a function that expected as parameter a function and it will return a function.
function func1(func) {
return function(summand) {
return func() + summand;
}
}
Then i defined the parameter function func2 in expression form
var func2 = function() {
return 3;
}
then call func1 and give func2 as pamerater. As result i have got a function back
var func3 = func1(func2);
then i execute function and pass 4 as parameter argument
var value = func3(4);
as result i've got 7. Then i overwrite func2 and return 100
var func2 = function() {
return 100;
}
then call func3 again and pass as parameter value 100.
var newValue = func3(100);
as result i've got 103. The first function that i defined(that return a function and takes function as parameter), will still used the first version of func2. This the power of closure, i know it.
But look at the following code, when i define func2 as function declaration not as expression, then func2 will overwrite
function func1(func) {
return function(summand) {
return func() + summand;
}
}
function func2() {
return 3;
}
var func3 = func1(func2);
var value = func3(4);
alert(value);
function func2() {
return 100;
}
var newValue = func3(100);
alert(newValue);
The first value is 104 and second is 200.
My question is, why when i use function declaration it will overwrite the old function, in this example is func2. But when i use function expression it will keep the reference to old func2.
It that because of function hoisting?
This is not because of closures.
Just like you figured out - this issue is because of function hoisting.
You can think of function declarations as "moved up" to the start of the current scope.
var f2 = function(){
return 50;
}
function f2(){
return 100;
}
In this case, f2 is 50 because it gets parsed in a way that's similar to:
var f2 = function(){
return 100;
}
var f2 = function(){
return 50;
}
Because of hoisting.
It is because of hoisting. Using the function statement rather than the function expression causes the function func2 to get hoisted to the top of the scope. You are overwriting func2 before any code in the scope gets executed.
because of hoisting you code actually looks like this:
function func1(func) {
return function(summand) {
return func() + summand;
}
}
function func2() {
return 3;
}
// Hoisted!!! Overwriting the previous func2 definition.
function func2() {
return 100;
}
var func3 = func1(func2);
var value = func3(4);
alert(value);
var newValue = func3(100);
alert(newValue);
Inside func1, func is a stable reference to the function that it was passed... It's just that you are passing the return 100; version before you think you are.
When you use the function foo() { ... } style, you are defining a function with the name foo. When you use the var foo = function() { ... } style, you are declaring a variable foo (which will be hoisted), and assigning it the anonymous function as its value.
It is ok to write
var a;
a = 2;
// ...stuff...
a = 3;
and we expect the value to be 3. So it is here, hoisting makes this like:
var func2;
func2 = function() { .. some stuff.. };
// ...stuff...
func2 = function() { .. some other stuff .. };
By comparison, I think if you define the functions, it will just take the one or other function definition in the initial parse.
I want to add another function called myFunction() into the CoreTeamObject, which is declared as local inside the anonymous function. Is this possible?
!function ($) {
var CoreTeamObject = function () {
var coreTeamVar1; // ...
this.someState = false; // ...
coreTeamFunction: function () { /* ... */ }
};
}(window.jQuery);
Normally, I'd use prototype with something like:
CoreTeamObject.prototype.myFunction = function(){
return
};
But I simply don't know how to access the object.
You simply can't. Variables within a function are private and cannot be accessed from the outside.
! function () {
var foo = 1;
}();
// Calling `foo` will throw a referenceError here.
// It doesn't even work with classes...
var foo = function () {
var bar = 2;
};
var bax = new foo();
// `bax.bar` doesn't exist.
However, there are workarounds. You could store them in a global variable (bad idea, though):
! function (w) {
w.foo = 3;
}(window);
// window.foo = 3
// foo = 3
Or if you can rewrite it to a class:
var foo = function () {
this.bar = 4;
};
var bax = new foo();
// bax.bar = 4
I hope this helps.