How does one implement 'protected variables' in javascript?
var DIM = {
makeOneDim: function(x) {
var magic = Math.random();
return {
dist: function() {
return x * magic;
}
};
},
makeTwoDim: function(x,y) {
var o = DIM.makeOneDim(x);
o.dist = function() {
magic *= Math.random();
return Math.sqrt(x*x+y*y) * magic;
// !! cant access 'private' variable magic !!
}
return o;
}
};
var o = DIM.makeOneDim(123);
var oo = DIM.makeTwoDim(1,2);
console.log(o.dist() + oo.dist());
I know in this example it would be possible to make a 'public getter', but i would still want to mutate the magic variable from within makeTwoDim's scope and hide it from its instances.
It would also be nice if I could somehow prevent recreating the dist functions on each creation of an instance.
Does this suit your needs? It uses a revealing module pattern to make magic private and return the functions. As such there is no need to call makeOneDim from makeTwoDim.
var DIM = (function () {
var magic = Math.random();
function makeOneDim(x) {
return {
dist: function() {
return x * magic;
}
};
}
function makeTwoDim(x, y) {
return {
dist: function() {
magic *= Math.random();
return Math.sqrt(x * x + y * y) * magic;
}
}
}
return {
makeOneDim: makeOneDim,
makeTwoDim: makeTwoDim
}
});
var o = DIM().makeOneDim(123);
var oo = DIM().makeTwoDim(1,2);
DEMO
There are a lot of ways you could engineer this, but the simplest would be to just keep the functions together:
var DIM = {
makeOneDim: function(x) {
var magic = Math.random();
var dist = function() {
return x * magic;
};
var dist2 = function(y, y) {
magic *= Math.random();
return Math.sqrt(x*x+y*y) * magic;
};
return {
dist : dist,
dist2 : dist2,
};
}
};
(and, did you really mean to change the value of magic with each call?)
You should be able to determine the value of magic within makeTwoDim by dividing o.dist() by x
var o = DIM.makeOneDim(x);
var magic = o.dist() / x;
console.log(magic)
You need to make environment with scope function.
The jQuery way :
var myClass;
(function () {
var a = 0; // private var
function protect_function() {
//...
}
window.myClass = {
public_function: function () { }
};
})();
I know I'm likely to collect rotten tomatoes, but I'd like to say that I disagree with the use of "protected" or "private" variables in the scope of JavaScript OOP. There are no builtin safeguards in JavaScript, developpers are doomed to be better than the others, that's it :-D Don't try to mimic Java, just take it as an opportunity to improve your programming skills. Thus, this code looks perfect to me:
AClass = function () {
// `rdm` should never change
this.rdm = Math.random();
};
Related
I'm trying to reduce the amount of global variables that my application uses, but I'm stuck trying to figure out how to structure my files.
This is the structure of the current application with some example variables and functions:
var x = 0;
var y = 1;
var z = 2;
foo = function(n) { return n + 1; }
bar = function(n) { return foo(n) * 2; }
This is the structure I'm moving to:
var app = new function() {
var x = 0;
var y = 1;
var z = 2;
foo = function(n) { return n + 1; }
bar = function(n) { return foo(n) * 2; }
}
Is there a way to define these variables and functions in other files (or in the same file but outside the function) and add them to the application namespace? I have a lot of variables and functions to define, and I just want to move everything from the global namespace to the application namespace in a way that all the variables and functions can continue to access each other. I also need to put them into multiple files, because I don't want to have an application file that's thousands of lines long.
Adding variables and functions to the application by making them properties (using 'app.functionName') would mean I would need to change how functions reference each other, and it doesn't seem like the right way to do it. For example, I couldn't just do this:
app.foo = function(n) { return n + 1; }
app.bar = function(n) { return foo(n) * 2; }
I would have to do this:
app.foo = function(n) { return n + 1; }
app.bar = function(n) { return app.foo(n) * 2; }
I can do the same with variables (using 'app.variableName'), but the same issue arises in that I can't just reference the variable anymore without putting 'app.' in from of the variable.
Maybe the structure of my application is just terrible and this isn't the way things are meant to be done in Javascript, but I can't seem to figure out how to implement my application without using lots of global variables or without just putting everything into one function in one file.
A more modern way would be to use a block statement and const to scope it locally to that:
var app = app || {};
{
const foo = app.foo = n => n + 1;
const bar = app.bar = n => foo(n) * 2;
}
The same can be achieved in older js with an IIFE:
var app = app || {};
(function() {
var foo = app.foo = function(n) {
return n + 1;
};
var bar = app.bar = function(n) {
return foo(n) * 2;
};
})();
Now you can put multiple js files with that structure into one page and then communicate with each other via app.sth().
This is still not really clean and you got a lot of boilerplate code. Therefore tools like Webpack were invented, so you can just write:
// Foo.js
export default function foo(n) { return n + 1 }
// Bar.js
import foo from "./foo";
export default function bar(n) { return foo(n) * 2; }
And webpack will generate you one tiny little (unreadable) js file out of it.
factory(n) returns objects with functions.
func1 function definition creates its own scope, and x inside this function references x = n + ''.
But func2 is a reference and the scope is wrong.
Is there a way to return an object from create so its functions were references (not separate definitions)?
Actually, I'm fine with func1 approach while function definition footprint is small. If it is a complex function it would be better not to clone this function into every object comming from factory(n). inner_func may not use this, it is simple function. Also I want to avoid new and this.
var factory = (function(){
var x = '!';
return function create(n){
var x = n + '';
return {
func1: function(y){return inner_func(x, y); },
/* vs */
func2: inner_func_api
}
}
function inner_func_api(y){ return inner_func(x, y); }
function inner_func(a, b){ return a + b; }
}());
var f1 = factory(2);
var f2 = factory(3);
var f1_func1 = f1.func1(4);
var f2_func1 = f2.func1(5);
var f1_func2 = f1.func2(4);
var f2_func2 = f2.func2(5);
console.log(f1_func1, f2_func1); //24 35
console.log(f1_func2, f2_func2); //!4 !5
You could define that function separately from the object initializer on the return statement:
var factory = (function(){
var x = '!';
return function create(n){
var x = n + '';
function func1(y) {
return inner_func(x, y);
}
return {
func1: func1,
/* vs */
func2: inner_func_api
}
}
function inner_func_api(y){ return inner_func(x, y); }
function inner_func(a, b){ return a + b; }
}());
However, it makes no practical difference, and it doesn't matter how big or complicated that function is. Function instances do take up space, but the code for the function is constant (immutable) and doesn't need to be part of every Function object created from the same piece of source code.
I'm trying to fully grasp JavaScript inheritance and encapsulation. Take the following example (and here is a fiddle of it):
myPage = {
someObj: function() {
var x = 0;
//PRIVATE: increment by 10
var inc10 = function() {
x = x+10;
};
//PUBLIC: increment
this.inc = function() {
x = x+1;
};
//PUBLIC: decrement
this.dec = function() {
x = x-1;
};
//PUBLIC: output the current value of x
this.getValue = function() {
return x;
}
inc10(); //as soon as obj1 is created lets add 10
this.inc(); //as soon as obj1 is created lets add 1 more
}
};
obj1 = new myPage.someObj(); //x starts out at 11
// obj1.inc10(); won't work because it's private, excellent
obj1.dec();
obj1.inc();
alert(obj1.getValue());
My question is about the inc() method. I need it to be callable from inside and outside of the object. Is this the proper way to do that?
I need it to be callable from inside and outside of the object. Is this the proper way to do that?
Your script does seem to work as expected already, you are calling the method as this.inc() in your constructor perfectly fine - not sure why it needs improvement.
You could however define it as a local function, which you then are going to export as a method - and have it still available "inside" as a local variable:
function SomeObj() {
// local declarations:
var x;
function inc10() {
x = x+10;
}
function inc1() {
x = x+1;
}
// exported as property:
this.inc = inc1; // <== the function from above, not a literal
this.dec = function() {
x = x-1;
};
this.getValue = function() {
return x;
};
// initialisation:
x = 0;
inc10();
inc1(); // this.inc() would still work
}
To call function from inside and outside without attaching it to an obj.
This should work ...
myPage = function() {
var x = 0;
//PRIVATE: increment by 10
var inc10 = function() {
x = x+10;
};
//PUBLIC: increment
this.inc = function() {
x = x+1;
};
//PUBLIC: decrement
this.dec = function() {
x = x-1;
};
//PUBLIC: output the current value of x
this.getValue = function() {
return x;
}
inc10(); //as soon as obj1 is created lets add 10
this.inc(); //as soon as obj1 is created lets add 1 more
};
obj1 = new myPage; //x starts out at 11
// obj1.inc10(); won't work because it's private, excellent
obj1.inc();
alert(obj1.getValue());
I know this question is already answered with limited capability but I want it with n number of time with n arguments?
function add(x) {
return function(y) {
if (typeof y !== 'undefined') {
x = x + y;
return arguments.callee;
} else {
return x;
}
};
}
add(1)(2)(3)(); //6
add(1)(1)(1)(1)(1)(1)(); //6
problem is this works only when I add extra empty brackets ()
it doesn't work if do this add(1)(2)(3)
reference question
Try this:
function add(x) {
var fn = function(y) {
x = x + y;
return arguments.callee;
};
fn.toString = function(){ return x; };
return fn;
}
The following code works exactly like you asked:
function add(a)
{
var c=a,b=function(d){c+=d;return arguments.callee;};
b.toString=function(){return c;}return b;
}
Do note that some operations will detect the result given as a function, but any functions that require a string or integer will see the proper value.
Try sending your numbers as an array and changing your function code to reflect these changes.
Note: Code untested.
function add(x) {
var result = 0;
for (i = 0; i < x.length;i++){
result+=x[i];
}
return result;
}
add(new Array(1,2,3));
Here's an easy one straight from the text book I can't seem to find.
I have a javascript function. I want it to contain a private variable which remembers its value between invocations.
Can someone jog my memory please.
Create it using a closure:
function f() {
var x = 0;
return function() {return x++;};
}
Then use it as follows:
> g = f()
function () {return x++}
> g()
0
> g()
1
> g()
2
var accumulator = (function() {
var accum = 0;
return function(increment) {
return accum += increment;
}
})();
alert(accumulator(10));
alert(accumulatot(15));
Displays 10 then 25.
I am not sure if I understood correctly but maybe something like this would do the trick :
function Foo() {
var x = "some private data";
return {
getPrivateData : function(){
return x;
}
};
};
var xx = new Foo();
xx.getPrivateData();
Here is a truly private implementation
(function() {
var privateVar = 0;
window.getPreviousValue = function(arg) {
var previousVal = privateVar;
privateVar = arg;
return previousVal;
}
})()
alert(getPreviousValue(1));
alert(getPreviousValue(2));
Cheers