private method in an javascript object - javascript

I've an object looks like this:
var obj ={
property : '',
myfunction1 : function(parameter){
//do stuff here
}
}
I need to set some private properties and functions, which can not be accessed/seen from outside of the object. It is not working with
var property:, or var myFunction1
Next question is, if I call a function within or outside the object, I always have to do this with obj.myfunction(). I would like to asign "this" to a variable. Like self : this. and call inside the object my functions and variables with self.property and self.myfunction.
How? :)

There are many ways to do this. In short: If dou define a function inside another function, your inner function will be private, as long as you will not provide any reference to if.
(function obj(){
var privateMethod = function() {};
var publicMethod = function() {
privateMethod();
...
};
return {
pubMethod: publicMethod
}
}());

var obj = (function() {
var privateProperty;
var privateFunction = function(value) {
if (value === void 0) {
return privateProperty;
} else {
privateProperty = value;
}
};
var publicMethod = function(value) {
return privateFunction(value);
}
return {
getPrivateProperty: function() {
return privateFunction();
},
setPrivateProperty: function(value) {
privateFunction(value);
}
}
})();
obj.setPrivateProperty(3);
console.log(obj.getPrivateProperty());
// => 3
console.log(obj.privateProperty);
// => undefined
obj.privateFunction();
// => TypeError: undefined is not a function

Use closures. JavaScript has function scope, so you have to use a function.
var obj = function () {
var privateVariable = "test";
function privateFunction() {
return privateVariable;
}
return {
publicFunction: function() { return privateFunction(); }
};
}();

Related

Assign an element to a variable

I have an Javascript object following the Module Pattern
var foo = (function() {
var obj = (function() {
var $button = $('#myButton');
var init = function() {
$button.hide();
};
return {
init: init
};
})();
return { obj: obj };
})();
If I call foo.obj.init(), the button should be hidden, and this does not occur.
I saw different questions here about the assignment of an element to a variable, but I think that the problem is with the object. Can't I access a private variable from a public method?
From my comment:
Do it as part of init... you can just declare the var in order to isolate the scope, and then modify it to actually set the button as part of init
Example:
var foo = (function() {
var obj = (function() {
var $button; //$('#myButton');
var init = function() {
if (typeof $button === 'undefined') {
// i would probably make the selector an argument to `init`
// if i were you.
$button = $('#myButton');
}
$button.hide();
};
return {
init: init
};
})();
return { obj: obj };
})();

Objects literal and 'this' in submodule pattern

Im working in a sub-module pattern code. Want to create sub-modules with objects literals, the problem is this for the objects inside the sub-module is MODULE and not my object literal. Any idea?
var MODULE.sub = (function () {
var myObject = {
key: value,
method: function () {
this.key // this = MODULE and not MyObject... :(
}
};
return myObject.method;
}(MODULE));
This works for me:
var MODULE = MODULE || {};
MODULE.sub = (function () {
return {
myObject : {
key : 10,
method : function() {
console.log(this.key);
}
}
};
})();
Then call it:
MODULE.sub.myObject.method();
You were only returning the method and not the key so "this" would be undefined. You could keep it private if you want like this and pass key in as a var:
var MODULE = MODULE || {};
MODULE.sub = (function () {
var key = 10,
return {
myObject : {
method : function() {
console.log(key);
}
}
};
})();
Solved... just return a function in MODULE.sub calling the public method. I don't know if is the best approach
var MODULE.sub = (function () {
var myObject = {
key: value,
method: function () {
this.key // this = myObject :)
}
};
return function () {
myObject.method();
}
}(MODULE));
The this keywords value depends on how the function is called. So if you assign that function to MODULE.sub, and then invoke it as MODULE.sub(…), then this will point to the MODULE of course. If you had invoked it as myObject.method(…), then this would point to that object.
So you either should expose the whole myObject (like in #BingeBoys answer), or do not export that function and expect it to be a method of myObject. Instead, you could use a bound one:
return myObject.method.bind(myObject);
or the explicit equivalent of that
return function() {
return myObject.method();
};
or you would not put the function as method on that object at all:
…
var myObject = {
key: value,
};
return function() {
myObject.key // no `this` here
…
};
…

Setting a variable in the closure scope

I think I understand why variables exist outside of the function they were declared in, because you're returning another function:
myFunction = function() {
var closure = 'closure scope'
return function() {
return closure;
}
}
A = myFunction(); // myFunction returns a function, not a value
B = A(); // A is a function, which when run, returns:
console.log(B); // 'closure scope'
The way that it's written now, calling A() is like a getter.
Q: How can I write myFunction so that calling A(123) is a setter?
Try the following:
myFunction = function() {
var closure = 'closure scope'
// value is optional
return function(value) {
// if it will be omitted
if(arguments.length == 0) {
// the method is a getter
return closure;
} else {
// otherwise a setter
closure = value;
// with fluid interface ;)
return this;
}
}
}
A = myFunction(); // myFunction returns a function, not a value
A(123); // set value
B = A(); // A is a function, which when run, returns:
console.log(B); // '123'
You could do something like this if you want both getter and setter for example:
var func = function() {
var closure = 'foo';
return {
get: function() { return closure; },
set: function(value) { closure = value; }
}
};
var A = func();
A.set('foobar');
console.log(A.get()); //=> "foobar"
Should be as simple as:
myFunction = function() {
var closure = 'closure scope'
return function(setTo) {
if (typeof setTo !== "undefined") {
closure = setTo;
return this; //support call chaining, good idea hek2mgl
} else {
return closure;
}
}
}
Since the closure variable is within the closure of the function's scope, you should be able to assign to it the same way you can read from it.
See jsFiddle: http://jsfiddle.net/WF4VT/1/
Another alternative would be to use a class and define getters and setters:
function MyClass(p){
this._prop = p;
}
MyClass.prototype = {
constructor: MyClass,
get prop(){
return this._prop;
},
set prop(p){
this._prop = p;
}
}
var myObject = new MyClass("TEST");
console.log(myObject.prop);
myObject.prop = "test";
console.log(myObject.prop);
Demo: http://jsfiddle.net/louisbros/bMkbE/
jsFiddle Demo
Have your returned function accept an argument. Use it as a setter:
myFunction = function() {
var closure = 'closure scope';
return function(val) {
closure = val;
return closure;
}
}
A = myFunction(); // myFunction returns a function, not a value
B = A(123); // A is a function, which when run, returns:
console.log(B); // 'closure scope'
Revisiting this question, I see that I could do it this way:
function outside() {
var result = 'initialized'
return inside
function inside(argVariable) {
if(arguments.length) {
result = argVariable
return this
} else {
return result
}
}
}
myFunction = outside() // outside returns a function
X = myFunction() // returns: 'initialized'
$('body').append(X + '<br>')
myFunction(123) // setter
X = myFunction() // returns: 123
$('body').append(X)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Get an object parameter value inside a jQuery function inside an object's method

I have this:
function test1()
{
this.count = 0;
this.active = 0;
this.enable = function () {this.active = 1;}
this.disable = function () {this.active = 0;}
this.dodo = function ()
{
$("html").mousemove(function(event) {
// I want to get here the "active" param value;
});
}
this.enable();
this.dodo();
}
instance = new test1();
instance.disable();
Let's say I want to check the active param of the test1 class in the commented place. How can I get it there ?
Thanks!
If you want access to all the member variables of the higher scope, you just need to save the this pointer from that scope into a local variable so you can use it inside the other scope:
function test1() {
this.count = 0;
this.active = 0;
this.enable = function () {this.active = 1;}
this.disable = function () {this.active = 0;}
var self = this;
this.dodo = function () {
$("html").mousemove(function(event) {
// I want to get here the "active" param value;
alert(self.active);
});
}
this.enable();
this.dodo();
}
instance = new test1();
instance.disable();
this.dodo = function ()
{
var active = this.active;
$("html").mousemove(function(event) {
alert(active);
});
}
When you call a function 'this' refers to the object the function was invoked from, or the newly created object when you use it together with the keyword new. For example:
var myObject = {};
myObject.Name = "Luis";
myObject.SayMyName = function() {
alert(this.Name);
};
myObject.SayMyName();
Note in JavaScript there are multiple ways to declare, define, and assign fields and methods to objects, below is the same code written more similarly to what you wrote:
function MyObject() {
this.Name = "Luis";
this.SayMyName = function() {
alert(this.Name);
};
}
var myObject = new MyObject();
myObject.SayMyName();
And yet another way to write the same thing:
var myObject = {
Name: "Luis",
SayMyName: function() {
alert(this.Name);
},
};
myObject.SayMyName();
There are also several different ways to invoke a function.

Why is arguments.callee.caller.name undefined?

How come this doesn't alert "http://127.0.0.1/sendRequest"? (Available at http://jsfiddle.net/Gq8Wd/52/)
var foo = {
sendRequest: function() {
alert(bar.getUrl());
}
};
var bar = {
getUrl: function() {
return 'http://127.0.0.1/' + arguments.callee.caller.name;
}
};
foo.sendRequest();
Putting a value in an object literal, as you're doing, doesn't affect the value at all.
var foo = {
sendRequest: ...
The function value is only affected by the function expression, which doesn't contain a name.
... function() {
alert(bar.getUrl());
}
You need to include the name you want in the function expression itself [fiddle].
var foo = {
sendRequest: function sendRequest() {
If you do this:
var foo = {
sendRequest: function() {
alert(bar.getUrl());
}
};
var bar = {
getUrl: function() {
return arguments.callee;
}
};
foo.sendRequest();
You will notice that the function doesn't have name which is true:
function() {
This is anonymous function.
You can name you method : sendRequest: function myMethodName() {
Although the function is stored under the object property foo.sendRequest, and thus can be invoked via foo.sendRequest(), that function itself doesn't actually have a name. That's why arguments.callee.caller.name is empty.
Because the function that is calling the function being called is an anonymous function (and hence, has no name).
Try:
function sendRequest() {
alert(bar.getUrl());
}
var foo = {
sendRequest: sendRequest
};
var bar = {
getUrl: function() {
return 'http://127.0.0.1/' + arguments.callee.caller.name;
}
};
foo.sendRequest();

Categories