A lot of people where confused by my last question. I hope I can clear things up with this one. HERE is what I need to do:
var arr = ["Init Value", "Does Not", "Matter"];
arr.onGet = updater; // Register arr with updater function
alert(arr[0]); // should return 1;
alert(arr[0]); // should return 2;
alert(arr[0]); // should return 3;
alert(arr[0]); // should return 4;
alert(arr[0]); // should return 5;
var counter = 0;
function updater(){
counter = counter + 1;
return counter;
}
See what I did there? Init value does not matter, it's the updater function that is pulling the values.
Now this does not work of course, since arr does not automatically call the function updater and there is no event onGet. Some people might say, well that's just crazy talk, how can you run a function when it's not even called. That is true, but a VARIABLE is called (in our case arr[0], so can't you just bind(link) it up to another function when arr[0] is called? In essence, this is an auto-updater, hence my question.
Also, I have given up trying to work this in IE7, how about just Google Chrome?
Solution by Skyd:
function onGet(obj) {
var index = 0;
var counter = 0;
for (var prop in obj) {
(function(thisIndex, thisProp) {
obj.__defineGetter__(thisIndex, function() {
counter = counter + 1;
return counter ;
});
})(index, prop)
index++;
};
obj.__defineGetter__("length", function() {
return 1000;
});
return obj;
}
var myObj = [100,200,300];
onGet(myObj);
alert(myObj[1]); // 1
alert(myObj[2]); // 2
alert(myObj[3]); // 3
alert(myObj.length); // 1000 <-- Arbitary value which you can change
You should look into javascript Setters and Getters, which lets you run functions when a certain property is being accessed or modified. It works great on objects. For arrays, its a little harder, since arrays can potentially have infinite properties (where properties are its indicies). If you have a fixed size array though, then something like this might work:
var arr = ["Fixed", "Array", "Size", "Will", "Not", "Ever", "Change"];
for (var i=0; i<arr.length; i++){
debug(i);
(function(index){
arr.__defineGetter__(index, function(){return updater();});
})(i);
}
alert(arr[0]) // will return results of updater() call;
It may be better to use a custom object with a getter/setter rather than using a fixed size array.
Also, look at these links: Getter/setter on javascript array? and http://javascriptweblog.wordpress.com/2010/11/15/extending-objects-with-javascript-getters/
Related
I was editing Chrome's sample oauth contacts extension
when I came across an interesting for-loop in line 7 of contacts.js:
for (var i = 0, contact; contact = contacts[i]; i++) {
variable i was never used in the body of the for loop, so it seemed like a typical "for...in" loop. I tried replacing the for-loop with
for (contact in contacts) {
but when I ran the extension, all my contacts came back undefined
Here is the full for-loop from the extension
for (var i = 0, contact; contact = contacts[i]; i++) {
var div = document.createElement('div');
var pName = document.createElement('p');
var ulEmails = document.createElement('ul');
pName.innerText = contact['name'];
div.appendChild(pName);
for (var j = 0, email; email = contact['emails'][j]; j++) {
var liEmail = document.createElement('li');
liEmail.innerText = email;
ulEmails.appendChild(liEmail);
}
div.appendChild(ulEmails);
output.appendChild(div);
}
What the code given does
What that does is evaluate what contacts[i] is and whether it is truthy or not, while at the same time caches the array element of the applicable index.
It's equivalent to the following code (note that in this example ++i has the same side effect as i++):
for (var i = 0; contacts[i]; ++i)
{ var contact = contacts[i];
// use contact
}
This could be interpreted as something like the following:
If !contacts[i] is false (i.e. it is truthy) continue the loop.
Otherwise, end the loop (it is falsy).
If the goal of that code was to iterate through all of an array, the problem would be that if you wanted to iterate through an element but it was falsy, it would end the entire loop instead of performing the (likely) intended effect. Take this example:
var foo = [1, 3, 5, 7, 9, 0, 2, 4, 6, 8];
// example for-loop given
for (var i = 0; foo[i]; ++i)
{ var bar = foo[i];
console.log('example: ' + bar);
}
// "normal" way of iterating through array
for (var i = 0, l = foo.length; i < l; ++i)
{ var bar = foo[i];
console.log('normal: ' + bar);
}
You'd find that the example only logs up to the number 9, while the "normal" way goes through the entire array. Of course though, if you could guarantee that all values within the array would be truthy (e.g. all array elements are objects), then this isn't that much of an issue.
What for-in does and why it doesn't work
You tried to replace that code with the following:
for (contact in contacts) { /*code here*/ }
However, this doesn't work for a number of reasons:
contact is a string of the property name, not the value of it. Take this example:
var foo =
{ bar1: 1
, bar2: 2
, bar3: 3
, bar4: 4
, bar5: 5 };
for (var i in foo) console.log(i);
What you get back is the property name (i.e. "bar1, bar2...") instead of the value. To do so for an object, you'd have to do something like the following:
for (var i in foo)
{ var bar = foo[i];
console.log(bar);
}
Now you should get back "1,2,3,4,5" on separate lines. If you got that, and some other things, you might be have defined items on Object.prototype - which is why it's generally a bad idea, unless it really makes the code cleaner, and there is a substantial purpose for doing so. To filter these out, add a hasOwnProperty() check:
for (var i in foo) if (foo.hasOwnProperty(i))
{ var bar = foo[i];
console.log(bar);
}
The upcoming version of ECMAScript (the "standard" version of JavaScript, minus the DOM) will have something called for-of loops, which will make it easier to do this sort of thing.
For-in loops generally aren't meant for arrays (it is possible, but it's just not a good idea usually). If you need to use for-in, you probably should be using an object instead - all arrays are objects, just that arrays have special internal length property and a few other things.
contact is an implied global, big no-no. In fact, implied globals are banned in strict mode. Use a variable declaration (inside or outside the for-in loop, doesn't matter) to solve this issue.
It's just learning about how JavaScript works and where to apply its various methods of doing things - some are more suitable than others in particular situations.
Here you are using an array,not an object.
Though using for..in outputs the same result as a normal for loop,this would be my answer.
MyRecommendation:
Use for..in for iterating over objects:
for..in iterates over properties of an object.
Note:the order of iteration is arbitary.
var Myobj = {
a: 1,
b: 2,
c: 3
};
for ( var prop in Myobj ) {
console.log(prop); // a...b...c
console.log(Myobj[prop]); // 1...2...3
}
but with this the problem is it will continue searching for enumerable properties up the prototype chain.So unless you dont use hasOwnProperty,it will iterate over local object and the prototype it is attached to.
//Improved version of above code:
for (var prop in Myobj) {
if ( Myobj.hasOwnProperty(prop) ) {
// prop is actually obj's property (not inherited)
console.log(prop); // a...b...c
console.log(Myobj[prop]); // 1...2...3
}
}
Use for loop for iteration over an array
for loop iterates over an array in sequential way.
ECMAScript 6 introduces generators, iterators and syntax sugar for iteration. Node.JS v0.11.4 with the flags
--harmony --use_strict --harmony_generators
understands the following generator
function* fibonacci() {
let previous = 0;
let current = 1;
while(true) {
let temp = previous;
previous = current;
yield current = temp + current;
}
}
I can then print the Fibonacci numbers less than 1000.
for(let value of fibonacci()) {
if(value > 1000) { break; }
console.log(value);
}
For this example a while loop instead of a for loop would be more natural, similar to
while(value of fibonacci() < 1000) {
console.log(value);
}
Can iteration of iterators be done with a while loop instead of a for loop?
You can call a generator step by step using next function
var sequence = fibonacci();
var value;
while ((value = sequence.next()) < 1000) {
console.log(value);
}
plus, maybe even a nicer solution would be something like:
function* fibonacci(limit){
let previous = 0;
let current = 1;
while(previous + current < limit) {
let temp = previous;
previous = current;
yield current = temp + current;
}
}
for(let value of fibonacci(1000)) {
console.log(value);
}
There are two possible ways I'd go on about this, given other languages that support this behavior:
1) One using Harmony proxies, which would let you doing meta-tables (kind of like in lua) and allow for lazy iterables. This would provide fhe following notation:
var arr = ...; // create the resource
for(var i=0;arr[i]<1000;i++){
arr[i]; // consume fibonacci numbers
}
2) The second using a take function letting you consume an iterable with .forEach like in C# or python. Which would allow the following notation:
takeWhile(fibGenerator,(item) => item<1000).forEach(... // consume with predicate
First approach - using harmony proxies
Note... for of loops through objects. It does not guarantee order at all. You can however do something like the following to get the notion of a lazy iterate.
You have to run node both with the --harmony_generators and --harmony_proxies flags:
var arr = ...; // create an array and proxy it, use a generator internally
arr[50]; // will calculate the 50th fibonacci element and return it.
arr[100];// will calculate the 100th fibonacci element and return it.
for(var i=0;arr[i]<1000;i++){
arr[i];//the i-th fibonacci number
}
It will only calculate numbers not fetched yet, this will allow you to use a simple for loop.
Here is how*:
var cache = [];
var handler = {
get: (function(){
function fibIterator(){
var t=0,a=0,b=0;
return function(){
t=a;
a+=b;
b=t;
return a;
}
}
var iterator = fibIterator();
return function (target, fibNumber) {
if (name in cache) {
return cache[name];
}
while(iterator < fibNumber){
// update indexes.
}
})()
}
};
var arr = Proxy.create(handler);
(Just don't expect it to be very fast)
*(using old proxy notation, since the new one isn't supported in node yet, will update once it gets support)
Side note, in JavaScript since functions can have internal state through closures, you don't even really need a generator
Second approach, using an iterator Take function.
This is what you'd normally do in languages like C# for this use case.
function takeWhile(generating, predicate){
var res = [],last;
do{
res.push(last=generating())
}while(predicate(last));
return res;
}
Then do something like
var res = takeWhile(fibIterator,function(item){
return item<1000;
});
res.forEach(function(){ ...
Or by count:
function take(generating,numToTake){
var res = [],num;
do{
res.push(last=generating())
}while(num++ < numToTake);
return res;
}
var res = take(fibIterator,1000);//first 1000 numbers
function *bar(){
yield 1;
yield 2;
yield 3;
return 4;
}
var value,
g = bar();
while((value = g.next()).value){
console.log(value);
}
//Object {value: 1, done: false}
//Object {value: 2, done: false}
//Object {value: 3, done: false}
//Object {value: 4, done: true}
Yes, it is possible to do this by using the regular generator methods.
var fib = fibonacci(), value;
while( (value = fib.next()) < 1000 ) {
console.log(value);
}
Although I seem to prefer the for...of statement which takes care of handling those next calls and dealing with StopIteration(if the sequence is finite).
I have a function that computes product of numbers in an array. The function should work like this
function prod (array){
//compute and return product
}
var arr = [1,2,3,0,4,5,0,6,7,8,0,9];
the function call:
prod(arr); //should return 6
prod(arr); //should return 20
prod(arr); //should return 336 (6*7*8)
prod(arr); //should return 9
prod(arr); //should return 0
prod(arr); //should return 0
prod(arr); //should return 0
In scheme, this is done with continuations, by storing previous state of the function (state of the function is captured just before its exit point) see this
So, in short, I want the javascript function return different values at different times with same parameter passed everytime.
JavaScript is a well designed language, so I hope there must be something which can emulate this. If there happens to be nothing in JS to do it, I do not mind to conclude with failure and move on. So, feel free to say its impossible.
Thanks.
JavaScript is not capable of supporting continuations: it lacks tail-calls.
Generally I would write this to use a "queue" of sorts, although CPS is also do-able (just have a finite stack :-) Note that other state can also be captured in the closure, making it an "explicit continuation" of sorts ... in a very gross sense.
Example using a closure and a queue:
function prodFactory (array){
// dupe array first if needed, is mutated below.
// function parameters are always locally scoped.
array.unshift(undefined) // so array.shift can be at start
// also, perhaps more closured state
var otherState
// just return the real function, yippee!
return function prod () {
array.shift()
// do stuff ... e.g. loop array.shift() and multiply
// set otherState ... eat an apple or a cookie
return stuff
}
}
var prod = prodFactory([1,2,3,0,4,5,0,6,7,8,0,9])
// array at "do stuff", at least until "do stuff" does more stuff
prod() // [1,2,3,0,4,5,0,6,7,8,0,9]
prod() // [2,3,0,4,5,0,6,7,8,0,9]
prod() // [3,0,4,5,0,6,7,8,0,9]
Happy coding.
"Finished implementation". Although this particular problem can avoid array mutation and just use an index: the same concepts apply. (Well, slightly different. With just an index the closed over variable would be altered, whereas with this approach an object is mutated.)
function prodFactory (array) {
array = array.slice(0)
return function prod () {
var p = 1
for (var n = array.shift(); n; n = array.shift()) {
p *= n
}
return p
}
}
var prod = prodFactory([1,2,3,0,4,5,0,6,7,8,0,9])
prod() // 6
prod() // 20
prod() // 336
You can give the function a property that will be remembered between calls:
function prod (array){
if (typeof prod.index === "undefined" || prod.currentArray != array) {
prod.currentArray = array;
prod.index = 0;
}
if (prod.index >= array.length)
return 0;
//compute and return product
var p = 1,
c;
while (prod.index < array.length) {
c = array[prod.index++];
if (c === 0)
return p;
p *= c;
}
return p;
}
I'm just guessing from your description of what should be returned that on an individual call to the function it should take the product of all of the numbers up to but not including the next zero or the end of the array. Calls after the end of the array should return 0? I may have the algorithm wrong for that, but you get the idea for what I'm suggesting to remember the function state between calls.
I've added a property to remember the current array being processed. As long as you keep passing the same array in to the function it will continue with the next elements, but if you pass a different array it will reset...
you can try something like
var index = 0;
function prod (array){
if(index < array.length){
var prod=1;
for(int i=index;i<array.length;i++){
if(array[i] != 0){
prod = prod * array[i];
}
else{
index = i+1;
return prod;
}
}
}
return 0;
}
this will update the global variable index everytime the function is called.
What you're looking for here are generators. As of 1.7, JavaScript supports them.
I am working on this animation function but I have a problem. I can't seem to perform what should be an easy task, I can not get the length of an object. If you check out that jsFiddle you can see that I am running alert(properties.length); and it is returning undefined. Can anyone see why this might be?
This is supported in node.js and newer environments.
var obj = {a: "a", b: "b"};
Object.keys(obj).length // 2
JavaScript object simply do not have a length property, only Arrays do. If you want to know the number of properties that are defined on a object, you have to iterate over them and count them.
Also, your for in loop is prone to bugs due extension of Object.prototype since in will traverse the complete prototype chain and enumerate all the properties that are on the chain.
Example
// Poisoning Object.prototype
Object.prototype.bar = 1;
var foo = {moo: 2};
for(var i in foo) {
console.log(i); // logs both 'moo' AND 'bar'
}
You have to use the hasOwnProperty method on the object in order to filter out those unwanted properties.
// still the foo from above
for(var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i); // only logs 'moo'
}
}
Many JavaScript frameworks out there extend the prototype, not using hasOwnProperty often leads to horrible bugs.
Update
Concerning the actual problem that your code is not animation both properties.
for(var p in properties) {
...
for(var i = 0; i <= frames; i++)
{
setTimeout((function(exti, element) {
return function() {
// p gets overriden by for outer for in loop
element.style[p] = original + (pixels * exti) + 'px';
}
// you need to pass in a copy of the value of p here
// just like you do with i and element
})(i, element), i * (1000 / 60), element);
}
....
}
If you are using Underscore.js, you can use _.size():
_.size({one : 1, two : 2, three : 3});
=> 3
Objects have no length, you'll need to use an array if you want that.
If you have to find the number of properties in an object there is only one way:
var length =0;
for(var i in obj) length++;
Here's #Junaid Qadir Shekhanzai's general function for "finding the length of an object" (which as we're told, should properly be called "counting the properties of an object"). It combines solutions from #Ivo Wetzel and #Martin Jespersen:
function countProperties(myObj){
var length = 0;
if(typeof myObj != 'object'){
return false;
}
for(var i in myObj) {
length++;
}
return length;
}
I wrote a simple map implementation for some task. Then, out of curiosity, I wrote two more. I like map1 but the code is kinda hard to read. If somebody is interested, I'd appreciate a simple code review.
Which one is better? Do you know some other way to implement this in javascript?
var map = function(arr, func) {
var newarr = [];
for (var i = 0; i < arr.length; i++) {
newarr[i] = func(arr[i]);
}
return newarr;
};
var map1 = function(arr, func) {
if (arr.length === 0) return [];
return [func(arr[0])].concat(funcmap(arr.slice(1), func));
};
var map2 = function(arr, func) {
var iter = function(result, i) {
if (i === arr.length) return result;
result.push(func(arr[i]));
return iter(result, i+1);
};
return iter([], 0);
};
Thanks!
EDIT
I am thinking about such function in general.
For example, right now I am going to use it to iterate like this:
map(['class1', 'class2', 'class3'], function(cls) {
el.removeClass(cls);
});
or
ids = map(elements, extract_id);
/* elements is a collection of html elements,
extract_id is a func that extracts id from innerHTML */
What about the map implementation used natively on Firefox and SpiderMonkey, I think it's very straight forward:
if (!Array.prototype.map) {
Array.prototype.map = function(fun /*, thisp*/) {
var len = this.length >>> 0; // make sure length is a positive number
if (typeof fun != "function") // make sure the first argument is a function
throw new TypeError();
var res = new Array(len); // initialize the resulting array
var thisp = arguments[1]; // an optional 'context' argument
for (var i = 0; i < len; i++) {
if (i in this)
res[i] = fun.call(thisp, this[i], i, this); // fill the resulting array
}
return res;
};
}
If you don't want to extend the Array.prototype, declare it as a normal function expression.
As a reference, map is implemented as following in jQuery
map: function( elems, callback ) {
var ret = [];
// Go through the array, translating each of the items to their
// new value (or values).
for ( var i = 0, length = elems.length; i < length; i++ ) {
var value = callback( elems[ i ], i );
if ( value != null )
ret[ ret.length ] = value;
}
return ret.concat.apply( [], ret );
}
which seems most similar to your first implementation. I'd say the first one is preferred as it is the simplest to read and understand. But if performance is your concern, profile them.
I think that depends on what you want map to do when func might change the array. I would tend to err on the side of simplicity and sample length once.
You can always specify the output size as in
var map = function(arr, func) {
var n = arr.length & 0x7fffffff; // Make sure n is a non-neg integer
var newarr = new Array(n); // Preallocate array size
var USELESS = {};
for (var i = 0; i < n; ++i) {
newarr[i] = func.call(USELESS, arr[i]);
}
return newarr;
};
I used the func.call() form instead of just func(...) instead since I dislike calling user supplied code without specifying what 'this' is, but YMMV.
This first one is most appropriate. Recursing one level for every array item may make sense in a functional language, but in a procedural language without tail-call optimisation it's insane.
However, there is already a map function on Array: it is defined by ECMA-262 Fifth Edition and, as a built-in function, is going to be the optimal choice. Use that:
alert([1,2,3].map(function(n) { return n+3; })); // 4,5,6
The only problem is that Fifth Edition isn't supported by all current browsers: in particular, the Array extensions are not present in IE. But you can fix that with a little remedial work on the Array prototype:
if (!Array.prototype.map) {
Array.prototype.map= function(fn, that) {
var result= new Array(this.length);
for (var i= 0; i<this.length; i++)
if (i in this)
result[i]= fn.call(that, this[i], i, this);
return result;
};
}
This version, as per the ECMA standard, allows an optional object to be passed in to bind to this in the function call, and skips over any missing values (it's legal in JavaScript to have a list of length 3 where there is no second item).
There's something wrong in second method. 'funcmap' shouldn't be changed to 'map1'?
If so - this method loses, as concat() method is expensive - creates new array from given ones, so has to allocate extra memory and execute in O(array1.length + array2.length).
I like your first implementation best - it's definitely easiest to understand and seems quick in execution to me. No extra declaration (like in third way), extra function calls - just one for loop and array.length assignments.
I'd say the first one wins on simplicity (and immediate understandability); performance will be highly dependent on what the engine at hand optimizes, so you'd have to profile in the engines you want to support.