Reseting a counter of a protected/nested variable in JavaScript - javascript

My intention is to create a safe counter and reset it by calling a function. I tried this code:
function ZeroCounter () { var c = 0 ; return function() { return ++c } };
const Counter = ZeroCounter();
But didn't work as I expected. ZeroCounter doens't reset var C. I noticed that function() return creates a new object.
var m = ZeroCounter(); var n = ZeroCounter();
m === n //return false
I tried a new code for ZeroCounter.
function ZeroCounter () { var c = 0 ; ret = function() { return ++c }; return ret };
In fact, no reasons for new results. So, What can I do to reach my intention: create a resetable nested variable? Or is it not possible in this way?

Basically, you're re-creating c each time you execute ZeroCounter. To get around that, move c outside of ZeroCounter.
var c = 0;
function ZeroCounter() {
return ++c;
}
var m = ZeroCounter();
var n = ZeroCounter();
console.log(m);
console.log(n);
If you want to contain c within ZeroCounter but still want the effect, use an Immediately Invoked Function Expression or IIFE
var ZeroCounter = (function () {
var c = 0;
return function () {
return ++c;
};
}());
var m = ZeroCounter();
var n = ZeroCounter();
console.log(m);
console.log(n);

You could use the parameter of the function and reset to a wanted value.
function counter() {
var c = 0;
return function(v) {
if (v !== undefined) c = v;
return ++c
};
}
const counterA = counter();
console.log(counterA());
console.log(counterA());
console.log(counterA());
console.log(counterA(0));
console.log(counterA());
console.log(counterA());

Related

Is it possible to use module pattern for more objects

var modularpattern = (function () {
var sum = 0;
return {
add: function () {
sum = sum + 1;
return sum;
},
}
} ());
var c = modularpattern;
c.add(); // 1
var d = modularpattern;
d.add(); // 2 but I want to be 1
console.log(modularpattern.add()); // alerts: 3
Is it possible to have more objects not only one? I want to have private fields but at the same time also having more that just one object?
Yes, that's easily possible by dropping the IIFE invocation to get a normal function instead. Only it's called factory pattern then, no longer module.
function factory() {
var sum = 0;
return {
add: function () {
sum = sum + 1;
return sum;
}
}
}
var c = factory();
c.add(); // 1
var d = factory();
d.add(); // 1
console.log(c.add()); // logs: 2
You can use the module pattern to create a factory which uses the module pattern to create more objects. Using your original example, it would look something like this:
var moduleFactory = (function() {
return {
create: function() {
return (function() {
var sum = 0;
return {
add: function() {
sum = sum + 1;
return sum;
}
}
})();
}
}
}
)();
var c = moduleFactory.create();
console.log(c.add()); //1
var d = moduleFactory.create();
console.log(d.add()); //1

Get return value of first function invocation match without invoking it twice

I have an array of function references.
I need to find the return value of the first function invocation that satisfies my match condition.
How can I avoid calling the matched function twice?
var f = function(x) { if (x === 10) return "ten"; }
var g = function(y) { if (y === 20) return "twenty"; }
var result = [f, g].find(m => m(10))
if (result) return result(10)
// this returns "ten"
Still not sure I fully understand you question. It seems to me that you want to iterate through an array of functions and return the result if the function called with the condition is truthy.
let fncaller = (fns, condition) => {
var result
for (var fn of fns) {
result = fn(condition)
if (result) { return result }
}
}
Can you use global variables?
var f = function(x) {
return x % 2 == 0
}
var g = function(y) {
return x % 2 == 1
}
var result = [f, g].find(function(m) {
window.blah = m(10);
return window.blah;
})
console.log(window.blah);
Or #DaveNewton's method. Not sure which is faster:
var f = function(x) {
if (x === 10) return "ten";
}
var g = function(y) {
if (y === 20) return "twenty";
}
var funcs = [f, g];
function checkIt(value) {
for (var i = 0, numFuncs = funcs.length; i < numFuncs; ++i) {
var v = funcs[i](value);
if (v) return v;
}
}
console.log(checkIt(20));
You could store in a variable as you go. It's better than using a global.
var f = function(x) { if (x === 10) return "ten"; };
var g = function(y) { if (y === 20) return "twenty"; };
function findValue(funcs, val) {
var result;
funcs.find(m => result = m(val));
return result;
}
console.log(findValue([f, g], 10));

Why does google main page use (0, obj.func)(args) syntax?

Sometimes I stared at js provided with google.com main page and found that they tended to use (0, obj.func)(args) syntax. Here are excerpts from the script:
var _ = _ || {};
(function (_) {
var window = this;
try {
_.mb = function (a) {
return (0, window.decodeURIComponent)(a.replace(/\+/g, " "))
};
_.zg = function (a, b) {
for (var c = a.length ? a.split("&") : [], d = 0; d < c.length; d++) {
var e = c[d];
if ((0, _.Ag)(e) == b) return (c = /=(.*)$/.exec(e)) ? (0, _.mb)(c[1]) : null
}
return null
};
_.Ag = function (a) {
return (a = /^(.+?)(?:=|$)/.exec(a)) ? (0, _.mb)(a[1]) : null
};
var Cg = function (a, b) {
var c = a.indexOf("?");
return 0 > c ? null : (0, _.zg)(a.substring(c + 1), b)
};
// Note var Cg called with no 0
var oca = function (a) {
this.A = Cg(a, "mods");
this.B = Cg(a, "ver")
};
} catch (e) {}
})(_);
Why prepending 0?
This makes an indirect call.
This ensures the context, in the called function, is the global one. This might be useful in an internal scope.
Example :
var a = {
b: function(){
console.log(this);
},
c1: function(){
this.b();
},
c2: function(){
(0, this.b)();
},
c3: function(){
(this.b)();
}
}
a.c1(); // logs a
a.c2(); // logs window
a.c3(); // logs a

array to an array of functions [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Javascript closure inside loops - simple practical example
You have an array of arbitrary values. Write a transform function in the global scope that will transform the array to an array of functions that return the original values, so instead of calling a[3], we will call a3.
For example I want:
var a = ["a", 24, { foo: "bar" }];
var b = transform(a);
a[1]; // 24
b[1](); // 24
However I am getting:
b
[function () {
return this.temp;
}, function () {
return this.temp;
}, function () {
return this.temp;
}]
Here is my code:
var a = ["a", 24, { foo: "bar" }];
var b = transform(a);
document.writeln(a[1]); // 24
document.writeln(b[0]()); // 24
document.writeln(b[1]()); // 24
function transform(array) {
b = [];
var i;
for (i = 0; i < array.length; i += 1) {
b[i] = function () {
return temp;
};
}
return b;
}
function transform(array) {
b = [];
var i;
for (i = 0; i < array.length; i += 1) {
b[i] = (function (x) {
return function () { return x; };
})(array[i]);
}
return b;
}
demo http://jsbin.com/udasoj/1/edit
Your code is correct if you call b[0](), then you should get the value returned.
Note that none of the existing answers will quite work; they will all produce functions that return that last value in a. var is function-scoped and interacts poorly with closures.
See this other answer I just wrote, which explains a similar problem: https://stackoverflow.com/a/14330595/17875
What is temp? It looks like the way to accomplish this is to generate the function via another function:
function transform(array) {
b = [];
var i;
for (i = 0; i < array.length; i += 1) {
b[i] = createReturnFunction(a[i]);
};
}
return b;
}
function createReturnFunction(value){
return function(){ return value; };
}
Working Fiddle: http://jsfiddle.net/eFWyf/

Set length property of JavaScript object

Let's say I have a JavaScript object:
function a(){
var A = [];
this.length = function(){
return A.length;
};
this.add = function(x){
A.push(x);
};
this.remove = function(){
return A.pop();
};
};
I can use it like so:
var x = new a();
x.add(3);
x.add(4);
alert(x.length()); // 2
alert(x.remove()); // 4
alert(x.length()); // 1
I was trying to make .length not a function, so I could access it like this: x.length, but I've had no luck in getting this to work.
I tried this, but it outputs 0, because that's the length of A at the time:
function a(){
var A = [];
this.length = A.length;
//rest of the function...
};
I also tried this, and it also outputs 0:
function a(){
var A = [];
this.length = function(){
return A.length;
}();
//rest of the function...
};
How do I get x.length to output the correct length of the array inside in the object?
You could use the valueOf hack:
this.length = {
'valueOf': function (){
return A.length;
},
'toString': function (){
return A.length;
}
};
Now you can access the length as x.length. (Although, maybe it's just me, but to me, something about this method feels very roundabout, and it's easy enough to go with a sturdier solution and, for example, update the length property after every modification.)
If you want A to stay 'private', you need to update the public length property on every operation which modifies A's length so that you don't need a method which checks when asked. I would do so via 'private' method.
Code:
var a = function(){
var instance, A, updateLength;
instance = this;
A = [];
this.length = 0;
updateLength = function()
{
instance.length = A.length;
}
this.add = function(x){
A.push(x);
updateLength();
};
this.remove = function(){
var popped = A.pop();
updateLength();
return popped;
};
};
Demo:
http://jsfiddle.net/JAAulde/VT4bb/
Because when you call a.length, you're returning a function. In order to return the output you have to actually invoke the function, i.e.: a.length().
As an aside, if you don't want to have the length property be a function but the actual value, you will need to modify your object to return the property.
function a() {
var A = [];
this.length = 0;
this.add = function(x) {
A.push(x);
this.length = A.length;
};
this.remove = function() {
var removed = A.pop();
this.length = A.length;
return removed;
};
};
While what everyone has said is true about ES3, that length must be a function (otherwise it's value will remain static, unless you hack it to be otherwise), you can have what you want in ES5 (try this in chrome for example):
function a(){
var A = [],
newA = {
get length(){ return A.length;}
};
newA.add = function(x){
A.push(x);
};
newA.remove = function(){
return A.pop();
};
return newA;
}
var x = a();
x.add(3);
x.add(4);
alert(x.length); // 2
alert(x.remove()); // 4
alert(x.length); // 1
You should probably use Object.create instead of the function a, although I've left it as a function to look like your original.
I don't think you can access it as a variable as a variable to my knoledge cannot return the value of a method, unless you will hijack the array object and start hacking in an update of your variable when the push/pop methods are called (ugly!). In order to make your method version work I think you should do the following:
function a(){
this.A = [];
this.length = function(){
return this.A.length;
};
this.add = function(x){
this.A.push(x);
};
this.remove = function(){
return this.A.pop();
};
};
These days you can use defineProperty:
let x = {}
Object.defineProperty(x, 'length', {
get() {
return Object.keys(this).length
},
})
x.length // 0
x.foo = 'bar'
x.length // 1
Or in your specific case:
Object.defineProperty(x, 'length', {
get() {
return A.length
}
})
function a(){
this.A = [];
this.length = function(){
return this.A.length;
};
this.add = function(x){
this.A.push(x);
};
this.remove = function(){
return this.A.pop();
};
};

Categories

Resources