var vehiclePage = (function(){
// defined these 3 public variable. to share between zoomNoShowFee & submitVehicle
this.obj;
this.rate;
this.idx;
var setPara = function(o,t,i){
this.obj = o;
this.rate = t;
this.idx = i;
}
return {
zoomNoShowFee : function(o,t,i){
// this is existing function. I need to access o,t,i inside submitVehicle function.
setPara(o,t,i); // wrote this private function to set values
},
submitVehicle : function(){
// here I need to access zommNoShowFee's parameter
alert(this.rate);
}
} // return
})();
vehiclePage.zoomNoShowFee(null,5,3);
vehiclePage.submitVehicle(); // getting undefined
zoomNoShowFee is already existing. Some other fellow developer wrote this. I want to use the values passed into zoomNoShowFee parameters inside submitVehicle.
For that I declared 3 public variables at the top and trying to store the values using setPara private function. so that I can access those public variables inside submitVehicle function.
But getting undefined when calling vehhiclePage.submitVehilce()
Fundamentally, I doing something wrong. But don't know where...
Thanks for any help...
In your use of the module pattern, you're mixing a few things. this.obj, this.rate and this.idx are properties of the wrong this object. In fact, they are properties of the global object, and you can verify this:
vehiclePage.zoomNoShowFee(null,5,3);
alert(rate); // alerts '5'
So, you have to store your values somewhere else. It's quite easy, though : just use regular variables instead of properties and you're good to go :
var vehiclePage = (function(){
var obj, rate, idx;
var setPara = function(o,t,i){
obj = o;
rate = t;
idx = i;
}
return {
zoomNoShowFee : function(o,t,i){
setPara(o,t,i);
},
submitVehicle : function(){
alert(rate);
}
} // return
})();
vehiclePage.zoomNoShowFee(null,5,3);
vehiclePage.submitVehicle();
Related
I have a function which has some variable since they are inside a function, they are local to function hence private. Now I may have many such variable, inorder to set a value and get the variable value from outside, I have to write set and get for every private variable.
Is there anyway in javascript to have common function for getting and setting all private variable(PrivateOne and PrivateTwo).
privateClosure = (function(){
var PrivateOne;
var PrivateTwo;
setPrivate = function(VariableName,Value)
{
VariableName = Value;
}
getPrivate = function(VariableName)
{
return VariableName;
}
return{setPrivate,getPrivate};
})();
// I want to do something like this
privateClosure.setPrivate(PrivateOne,10);
privateClosure.getPrivate(PrivateOne);
privateClosure.setPrivate(PrivateTwo,20);
privateClosure.getPrivate(PrivateTwo);
//Only one Function for all the private variable in closure.
Is there anyway in javascript to have common function for getting and setting all private variable(PrivateOne and PrivateTwo).
You could closure a Map:
var data = (function(){
var lookup = new Map();
return {
get(v){
return lookup.get(v);
},
set(a,v){
return lookup.set(a,v);
}
}
})();
So you can do:
data.set("a",1);
alert( data.get("a"));
Sure there is: eval does everything you want1.
const privateVars = (function(){
var privateOne;
var privateTwo;
return {
setPrivate(variableName, value) {
eval(`(v) => { ${variableName} = v; }`)(value);
},
getPrivate(variableName) {
return eval(variableName);
};
}
}());
1: …and is, of course, totally unreasonable. Don't use this.
However, if you want something for
getting and setting all private variables
I wonder why they are private at all and you don't just use an object with public properties.
I am trying to access a variable which exists in another function, but I am not able to, it gives me undefined for the function through which (getMess() as below) I am doing that.
As per the code below, I want the "value1" accessed through myfunction1, as shown below.
Code:
var namespace ={
myfunction1: function(){
namespace.myfunction2.getMess(); // I need to access value1 here in this function
},
myfunction2: function(message1,message2){
var value1 = message1;
var value2 = message2;
return{
getMess: function(){ return value1;}
getLab: function() { return value2;}
}
}
}
namespace.myfunction2("hello","bye"); // this basically just sets the 2 values on page load
I just posted another question with the original problem : Read resource file entry in javascript - MVC application
You could do:
myfunction2: function(message1,message2){
var value1 = message1;
var value2 = message2;
namespace.myfunction2.getMess: function(){ return value1;}
namespace.myfunction2.getLab: function() { return value2;}
}
but that's pretty awful (assigning properties to a function object). Better to refactor the whole thing using the module pattern to emulate private and privileged members.
e.g.
var namespace = (function() {
// Private members
var value1, value2;
return {
// Privileged methd to read private member values
fn1: function() {
return namespace.fn2.getMess1();
},
// Privileged methods to set and get private member values
fn2: {
setMess: function(message1, message2) {
value1 = message1;
value2 = message2;
},
getMess1: function() {
return value1;
},
getMess2: function() {
return value2;
}
}
}
}());
namespace.fn2.setMess("hello","bye");
alert(namespace.fn1()); // hello
This seems very strange to me, but first off you were retuning an object and missing a , inbetween the 2 functions you were trying to return.
var namespace ={
myfunction1: function(){
var jamie = namespace.myfunction2("hello","bye"); // save returned value so we can use them later.
console.info(jamie.getMess); //as we already executed the value just refer to them
},
myfunction2: function(message1,message2){
var value1 = message1;
var value2 = message2;
return{
getMess: function(){ return value1;}(), //return self executing functions to return values without the need to run them again.
getLab: function(){ return value2;}()
}
}
}
namespace.myfunction1();
While I'm still not sure what you're trying to achieve this is how I would pass values between 2 functions whilst not declaring variables to namespace and just assigning values globally that way.
Basicly, i want "theId" to be equal to what "getId" returns. But how?
var Quiz = {
getId : function() {
var params = 1;
return params;
},
theId : getId(),
};
An object literal can't refer to properties/methods within itself, because at the time the object literal is evaluated the object doesn't exist yet. You have to do it as a two-step process:
var Quiz = {
getId : function() {
var params = 1;
return params;
}
};
Quiz.theId = Quiz.getId();
Note that that sets theId to whatever getId() returned at that time, it doesn't somehow automatically update theId if your real-world function is more dynamic than your example and potentially returns different values each time it's called.
Alternatively if the function is declared before the object you can create both object properties at once, with one being a reference to the function and the other being the result of calling it.
Seems a bit like a duplicate of Self-references in object literal declarations, but you could use a simple getter function for your property:
var Quiz = {
get theID() {
var params = 1;
return params;
}
};
Just for the kicks i am trying to create a simple data object in javascript. Here is the code.
var roverObject = function(){
var newRover = {};
var name;
var xCord;
var ycord;
var direction;
newRover.setName = function(newName) {
name = newName;
};
newRover.getName = function() {
return name;
};
newRover.setDirection = function(newDirection) {
direction = newDirection;
};
newRover.getDirection = function() {
return direction;
};
newRover.setXCord = function(newXCord) {
xCord = newXCord;
};
newRover.getXCord = function() {
return xCord;
};
newRover.setYCord = function(newYCord) {
yCord = newYCord;
};
newRover.getYCord = function() {
return yCord;
};
newRover.where = function(){
return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction;
};
return newRover;
};
rover1 = new roverObject();
rover2 = new roverObject();
rover1.setName("Mars Rover");
rover1.setDirection("NORTH");
rover1.setXCord(2);
rover1.setYCord(2);
console.log(rover1.where());
console.log(rover1);
rover2.setName("Moon Rover");
rover2.setDirection("SOUTH");
rover2.setXCord(1);
rover2.setYCord(1);
console.log(rover2.where());
console.log(rover2);
There are few questions that I have around this creation.
I want to create an object where the properties/attributes of object are private and not visible to world. Am I successful in doing that? Can I really not access the object attributes?
Is there a better way to create this kind of object?
If I want to inherit this object, I should do a newObject.prototype = roverObjectwill that work? And will that make sense most of all.
Finally I have a wierd problem. Notice the last method of objet "where" which returns a concatenated string. Here I tried following code instead.
newRover.where = function(){
return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction;
}();
and then did a following console.log
console.log(rover1.where);
console.log(rover2.where);
It threw following error for me:
cannot access optimized closure
Why would it say that? What am I doing wrong?
Thanks for all the help. Any review comments would be appreciated too!
Cheers
Am I successful in doing that? Can I really not access the object attributes?
Indeed. You don't have object attributes, you have local variables in the roverObject function. Local variables can't be accessed from outside, only from the functions inside the roverObject function that have a closure over them.
That you are calling roverObject as a constructor, with new roverObject, is irrelevant, as you are returning a different object from the function. Saying var rover1= roverObject() without the new would do exactly the same thing. Notably the object returned by [new] roverObject is a plain Object as you created it from {}; rover1 instanceof roverObject is false.
If you wanted instanceof to work, you would have to call with new, and use this instead of newRover in the constructor function.
If I want to inherit this object, I should do a newObject.prototype = roverObject will that work? And will that make sense most of all.
No. You currently have no allowance for prototyping. You are using a separate copy of each method for each instance of the roverObject. You can do certainly objects this way but it's a different approach than prototyping. If you wanted to make something like a subclass of roverObject in the arrangement you have now, you'd say something like:
function AdvancedRover() {
var rover= new roverObject();
rover.doResearch= function() {
return rover.where()+' and is doing advanced research';
};
return rover;
}
Note since the ‘private’ local variables in the base class constructor really are private, even the subclass cannot get at them. There's no ‘protected’.
newRover.where = function(){ ... }();
What's that trying to do? I can't get the error you do; all the above does is assigns the string with the location to where (before the setter methods have been called, so it's full of undefineds).
Is there a better way to create this kind of object?
Maybe. see this question for a discussion of class/instance strategies in JavaScript.
Q1: you can create 'private' members in javascript 'classes'. In javascript, privacy is not determined by any access specifier. Instead, access needs to be specifically instrumented. Example:
function MyClass() {
this.val = 100; // public;
var privateVal = 200;
function getVal() { return this.val; } // private method;
this.getPrivateVal = function() { // public method, accessor to private variable
return privateVal;
}
}
Object scope in javascript is governed by a queer concept called closures. AFAIK, there is no parallel concept in any other popular launguage like C+/Java etc.
While I understand what closures are, I cannot put it in words. Perhaps a demonstration will help you:
function closureDemo() {
var done=false;
function setDone() { done=true; }
doLater(setDone);
}
function doLater(func) { setTimeout(func,1000); }
closureDemo();
now, while setDone is called from within doLater, it can still access done in closureDemo, even though done is not in scope (in the conventional procedural sense).
I think you will understand more when you read this.
Q2: I can only say what I do; I don't know if it is better or not. If I wrote your code, it would look like this:
function RoverObject() {
var newRover = {}; // privates
var name;
var xCord;
var ycord;
var direction;
this.setName = function(newName) {
name = newName;
};
this.getName = function() {
return name;
};
this.setDirection = function(newDirection) {
direction = newDirection;
};
// and so on...
this.where = function(){
return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction;
};
}
var rover1 = new RoverObject();
Points to note:
capitalization of "class name"'s first letter
use of this instead of roverObject
this function is a pure constructor. it returns nothing.
Q3: if you want to do inheritance, then my method (use of this) will not work. Instead, the public methods should be a part of the prototype of RoverObject. Read this. Excellent material.
Hope that helps.
EDIT: There is a problem with the way your code is doing work. Problems:
your function does not do what its name suggests. Its name had better be createRoverObject, because that's exactly what it is doing. It is not working like a class constructor
the methods supported by your class are part of the object, but the data members are not. While this may work (and it is not, as your console.log() problem suggests), it is not a good way to implement a class in javascript. The problem here is of closures. Again, i'm unable to articulate what the problem specifically is, but I can smell it.
With regards to 4. - you are trying to log the function, not the result of calling the function. Should be console.log(rover1.where()); My guess firebug(I assume it's firebug's console.log) does not like to log function definitions.
EDIT Oh I get it, you are actually executing the where funcion when you assign rover.where. Are you trying to get what looks like a property to actually be a function? If that's the case it won't work. It will have to be a function if you want it to be evaluated when it's called.
What happens in you case where gets executed in the constructor function. At that point you are still creating the roverObject closure and hence it's too early to access it's private variables.
This is just addressing point 1 of your post.
Here's a good article on javascript private members and more:
Private Members in JavaScript
Defining your object like this gives you private members.
function RolloverObject() {
var name;
var xCord;
var ycord;
var direction;
this.setName = function(newName) { name = newName; };
this.getName = function() { return name; };
this.setDirection = function(newDirection) { direction = newDirection; };
this.getDirection = function() { return direction; };
this.setXCord = function(newXCord) { xCord = newXCord; };
this.getXCord = function() { return xCord; };
this.setYCord = function(newYCord) { yCord = newYCord; };
this.getYCord = function() { return yCord; };
this.where = function() {
return "Rover :: " + name + " is at Location(" + xCord + "," + yCord + ") pointing to " + direction;
};
}
var rolloverObject = new RolloverObject();
I need to create simple reusable javascript object publishing several methods and parameterized constructor. After reading through several "OOP in JavaScript" guides I'm sitting here with an empty head. How on the Earth can I do this?
Here my last non-working code:
SomeClass = function(id) {
this._id = id;
}
(function() {
function intFun() {
return this._id;
}
SomeClass.prototype.extFun = function() {
return incFun();
}
})();
This is my usual approach:
MyClass = function(x, y, z) {
// This is the constructor. When you use it with "new MyClass(),"
// then "this" refers to the new object being constructed. So you can
// assign member variables to it.
this.x = x;
...
};
MyClass.prototype = {
doSomething: function() {
// Here we can use the member variable that
// we created in the constructor.
return this.x;
},
somethingElse: function(a) {
}
};
var myObj = new MyClass(1,2,3);
alert(myObj.doSomething()); // this will return the object's "x" member
alert(myObj.x); // this will do the same, by accessing the member directly
Normally the "this" keyword, when used in one of the object's methods, will refer to the object itself. When you use it in the constructor, it will refer to the new object that's being created. So in the above example, both alert statements will display "1".
An exception to this rule is when you pass one of your member functions somewhere else, and then call it. For example,
myDiv.onclick = myObj.doSomething;
In this case, JavaScript ignores the fact that "doSomething" belongs to "myObj". As a result, the "this" inside doSomething will point to another object, so the method won't work as expected. To get around this, you need to specify the object to which "this" should refer. You can do so with JavaScript's "call" function:
myDiv.onclick = function() {
myObj.doSomething.call(myObj);
}
It's weird, but you'll get used to it eventually. The bottom line is that, when passing around methods, you also need to pass around the object that they should be called on.
I usually don't worry too much about hiding the internals, although I do prefix them with underscores to mark them as not intended to be used outside the "class". Normally what I will do is:
var MyClass = function() {};
MyClass.prototype = {
_someVar : null,
_otherVar : null,
initialize: function( optionHash ) {
_someVar = optionsHash["varValue"];
_otherVar = optionsHash["otherValue"];
},
method: function( arg ) {
return _someVar + arg;
},
};
And use it as so...
var myClass = new MyClass( { varValue: -1, otherValue: 10 } );
var foo = myClass.method(6);
All vars are private:
SomeClass = function (id) {
var THIS = this; // unambiguous reference
THIS._id = id;
var intFun = function () { // private
return THIS._id;
}
this.extFun = function () { // public
return intFun();
}
}
Use THIS within private methods since this won't equal what you might expect.
From http://learn.jquery.com/code-organization/concepts/#the-module-pattern:
// The module pattern
var feature = (function() {
// private variables and functions
var privateThing = "secret";
var publicThing = "not secret";
var changePrivateThing = function() {
privateThing = "super secret";
};
var sayPrivateThing = function() {
console.log( privateThing );
changePrivateThing();
};
// public API
return {
publicThing: publicThing,
sayPrivateThing: sayPrivateThing
};
})();
feature.publicThing; // "not secret"
// logs "secret" and changes the value of privateThing
feature.sayPrivateThing();
So using returning an object that aliases its "methods" could be another way to do it.
I've read from http://www.amazon.com/Programming-Oracle-Press-Poornachandra-Sarang-ebook/dp/B0079GI6CW that it is always good practice to use getters and setters rather that accessing the variable directly from outside the object, so that would eliminate the need of returning variables by reference.
BTW you could just use this.variable to reference/declare a public variable and var variable to declare a private variable.
I know this is a late answer, but I hope it helps anyone who reads it in the future.