Referencing "private methods" in a closure - javascript

var Foo = (function () {
var foo = function() { };
var privateMethod = function(){ };
foo.prototype = {
init: function() {
console.log(this.privateMethod); //undefined
}
};
return foo;
})();
I know that I can access privateMethod directly without using the this pointer. But since I come from the c# world, I would like to use it for readability purposes.
Is there any way to reference my "private methods" using a pointer?

You can't. You can only use this to refer to "public" methods. If you really want to use a something.method notation, you could use:
var Foo = (function () {
var foo = function() { };
var private = {
privateMethod : function(){ };
}
foo.prototype = {
init: function() {
console.log(private.privateMethod);
}
};
return foo;
})();

privateMethod is not specific to each instance of foo. Just reference it without the this. qualifier—although you probably want to log the results of a function call, not the function itself:
console.log(privateMethod());

Related

JavaScript Function Hoisting in my Object

I have created an object and am attaching a bunch of functions to the object. I am concerned about how the ordering of the functions effects when I can call my functions. In my example below, I must define my functions first before I can use them. My problem with this is that I cannot call init() immediately until I have defined it. Init() will contain a bunch of other functions that it will need to call, which will have to be placed above init(). So in the end, init() will have to be the very last function defined in my object. I believe this is related to Hoisting.
My question is if there is a way for me to call a function before defining it? Is there some sort of way to create a 'placeholder' function like in C?
https://jsfiddle.net/13hdbysh/1/
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
//this will error
foo.init();
foo.init = function() {
console.log('init()');
};
})();
What you're asking deals with how objects store member data. This can be seen in a weird light because of prototypal inheritance. Javascript by default will parse naked functions before they execute.
Example:
(function() {
init();
function init()
{
console.log("Init");
}
)};
This gets muddied when storing behavior as a member to an object. Because prototypal inheritances dynamic functionality you need to declare your members before accessing them. This is Javascript's main difference from traditional OOP languages.
You mentioned, "is there a way to create a 'placeholder' function like in C." You can, but not in the same way. You can assign it to a naked function and assign that to your object. Look in my example, the hello function.
Alternatively you can store the behavior on the prototype of your object and override it when necessary.
Example:
function hello()
{
console.log("Hello my name is "+this.name);
}
(function() {
var something = function(name) {
this.name = name;
};
something.prototype.initTwo = function() {
console.log("My Name is: "+this.name);
};
var thingOne = new something("Thing One");
thingOne.init = "SomeThing";
var thingTwo = new something("Thing Two");
thingTwo.init = function() {
console.log(this.name);
};
thingTwo.initTwo = function() {
console.log("SomethingTwo is Named: "+this.name);
};
thingTwo.hello = hello;
console.log(thingOne.init);
thingTwo.init();
thingOne.initTwo();
thingTwo.initTwo();
thingTwo.hello();
}) ();
Demo: Fiddle
Documentation on objects in javascript.
Try using similar IIFE pattern
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
//this will error
// foo.init();
foo.init = (function _foo() {
console.log('init()');
this.init = _foo;
return this.init
}).call(foo);
foo.init()
})();
jsfiddle https://jsfiddle.net/13hdbysh/2/
I am not sure why would you wanna call it before it is defined but here is how to do it:
foo = window.foo || { init: function() { } };
How about declaring it as a local variable first.
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
var initFunction = function() {
console.log('init()');
};
//this will no longer error
initFunction();
foo.init = initFunction;
})();
Init() will contain a bunch of other functions that it will need to call, which will have to be placed above init().
You are operating under a misapprehension.
A function must be defined before you call it, not before you define another function which will call it later.
Just define all your functions and then start calling them.
(function() {
foo = window.foo || {};
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.init = function() {
console.log('init()');
};
foo.init();
foo.helloWorld();
})();
As far as hoisting is concerned, function declarations (you only have function expressions) are hoisted, but they create locally scoped variables, not object properties. You would have to assign them to object properties before you could call them as such, and that assignment wouldn't be hoisted.
It's throwing an error because you're calling the method init() before it's declared.
This way will works
foo.init = function() {
console.log('init()');
};
foo.init();
Since foo is an object, you can put those functions into an object so that will be assigned to foo once window.foo is null
(function() {
foo = window.foo || {
helloWorld: function() {
console.log('helloWorld()');
},
init: function() {
console.log('init()');
}
};
//this will not error
foo.helloWorld();
foo.init()
})();

var self=this multiple times in methods defined on the prototype?

If you have to use var self=this for methods on the prototype object. Will you write var self=this inside each method?
Is there any way to avoid writing var self =this inside all methods?
function Test () {
}
Test.prototype.method1 = function () {
var self = this;
};
Test.prototype.method2 = function () {
var self = this;
};
You only need to create an alias for the this context if you are going to be introducing new contexts with function literals that still need to access the class's this context.
function Test () {}
Test.prototype.method1 = function () {
// This is fine.
this.someProperty = 123;
this.doSomething();
};
Test.prototype.method2 = function () {
var self = this;
var callback = function() {
// The `this` here is no longer the same `this` as outside the function.
self.someProperty = 456;
};
var anotherCallback = function() {
// No reference to the class's `this` needed here.
alert('Boo');
};
this.doAsyncThing(callback);
};
Alternatively, you can use Function.prototype.bind to force a this context:
var callback = function() {
this.someProperty = 456;
}.bind(this);

Javascript object methods

Why I cannot do this?
var MyObject = {}
MyObject.foo = function(){
this.sayhello = function(){
alert('Hello');
}
}
MyObject.foo.sayhello();
Any ideas on how it could be done?
within foo, this references MyObject, which means that after:
MyObject.foo();
you can call:
MyObject.sayhello();
If you want to be able to call MyObject.foo.sayhello(), you need sayhello to be a function on MyObject.foo:
var MyObject = {}
MyObject.foo = function () {...};
MyObject.foo.sayhello = function () {
alert('hello');
}
If you don't need foo to also be a function, you could simply declare:
var MyObject = {
foo: {
sayhello: function () {
alert('Hello');
}
}
}
which would allow you to call:
MyObject.foo.sayhello();
You have to call MyObject.foo() first so that the this.sayhello function actually gets added. Then you should beable to call MyObject.foo.sayhello();
var MyObject = {}
MyObject.foo = {
sayhello: function(){
alert('Hello');
}
}
MyObject.foo.sayhello();
That is because the function does not yet exist. Therefore you must call foo first. What you do is calling the function sayhello from the property foo. But you don't have a property foo. You have a function foo.
But you can also do this and make it chain, like jQuery does:
var MyObject = {}
MyObject.foo = function(){
this.sayhello = function(){
alert('Hello');
}
return this;
}
MyObject.foo().sayhello();
Make a function sayhello inside object foo, so not a chained function. But an object inside an object with a function.
var MyObject = {
foo : {
sayhello : function(){
alert("hello");
}
}
}
MyObject.foo.sayhello(); // Now does work!

Private var inside Javascript literal object

How can I declare a private var inside a literal object? Becasuse I've this code:
var foo = {
self: null,
init: function() {
self = this;
self.doStuff();
},
doStuff: function() {
//stuff here
}
}
This works perfectly, but if I have some objects, the var "self" it will override.. apparently it's a global var.. and I cannot use the restricted word "var" inside this object..
How can I solve this, or make an NameSpace for each object?
Thanks!
You can create a function scope to hide the variable:
var foo = (function() {
var self = null
return {
init: ...,
doStuff: ...
};
})();
Though it is not clear what self is supposed to do here, and how foo is used.
You have to use this:
init: function() {
this.self = this;
this.self.doStuff();
},
edit However, it's still a property of the "foo" object, and it's not super-clear where you're getting instances of "foo" from. In other words, the way your code is written, there's only one object.
Alternatively, you could create your object with a closure:
var foo = function() {
var self = null;
return {
init: function() {
self = this;
self.doStuff();
},
doStuff: function() {
//stuff here
}
};
}();
You are not even using the property that you have created. Instead you create another global variable with the same name. Use the this keyword to access properties:
var foo = {
self: null,
init: function() {
this.self = this;
this.self.doStuff();
},
doStuff: function() {
//stuff here
}
}
(Although saving this in a property is truly pointless...)
If you want a local variable in the object, create a closure for it:
var foo = (function(){
var self = null;
return {
init: function() {
self = this;
self.doStuff();
},
doStuff: function() {
//stuff here
}
};
}());

Reference Instance Variables in Javascript Constructor

I'm trying to maintain state on an object by doing something like this:
obj = function() {
this.foo = undefined;
this.changeState = function () {
(function () { this.foo = "bar" })(); // This is contrived, but same idea.
};
};
I want to set the instance variable foo to "bar" when I call the changeState method.
For instance:
o = new obj();
o.changeState();
alert(o.foo); // This should say "bar"
As far as I can tell, what is happening is that "this" in the inner anonymous function is pointing to window. I'm not sure what's going on.
Am I on the right track? Is there a better approach?
this topic comes up a lot, but it's hard to serach for since "this" is removed from SO searches.
Basically, in JavaScript, this always refers to the calling object, not the context object. Since here we call o.changeState() from the global scope, this refers to window.
You actually don't need the inner function for the closure to work in this case - the changeState function itself is enough to close a lexical scope.
obj = function()
{
var self = this;
this.foo = undefined;
this.changeState = function()
{
self.foo = "bar";
}
}
Unless you specify a this context when calling a function the default will be the global (which in browsers is window).
Alternatives are:-
obj = function() {
this.foo = undefined;
this.changeState = function () {
(function () { this.foo = "bar" }).call(this); // This is contrived, but same idea.
};
};
or:-
obj = function() {
var self = this;
this.foo = undefined;
this.changeState = function () {
(function () { self.foo = "bar" })(); // This is contrived, but same idea.
};
};
function obj() {
this.foo = undefined;
this.changeState = function () { this.foo = "bar" };
};
var o = new obj();
o.changeState();
alert(o.foo);
works for me. I'm not sure why you would want to use a self-invoking function just to assign a function reference, nor why you use a function expression for your constructor rather than a function declaration.
I figured it out. Just needed to save a reference to the current context and use that in the inner anonymous function:
obj = function() {
this.foo = undefined;
var self = this;
this.changeState = function () {
(function () { self.foo = "bar" })();
};
};

Categories