playground icon indicating copy to clipboard operation
playground copied to clipboard

Bugfix: Iterate over array in 'loadImages'

Open frondeus opened this issue 7 years ago • 5 comments

Problem

Let's assume we have this code:

this.loadImages('a.png', 'b.png');

Now, we know for sure we want to load a.png and b.png, This is easy as pie, we just need to iterate over arguments.

However we can also write:

this.loadImages(['a.png', 'b.png']);

This is more tricky. We need to distinguish a string from array. So what do we do? We check if arg is an object.

If it's true, we just iterate over all elements in array. Well, how do we do it? We use

for (var key in arg) ...

And it usually works just fine. What is more now we can write

this.loadImages({a: 'a.png', b: 'b.png });

and it should work.

But there is one small problem: Using for ... in with array iteration is a bad idea

Somewhere deep in your or other JavaScript library there can be something like this:

Array.prototype.foo = 1; //or
Array.prototype.remove = function() { ...

Now foo is a part of EVERY array and it will show up inside our for ... in loop as a value of key.

Solution

I'm not sure if this is 100% correct solution

When we operate on array we should do basic for loop

for(var key = 0; key < arg.length; key++)

Now we will iterate only over our desired elements. But this has drawback - we can't use object syntax anymore.

So before loop we could check if object is an Array. Unless it is we use old for (var key in arg) method, otherwise new for(key = 0; ....

frondeus avatar Sep 02 '16 16:09 frondeus

Did this happened to you tho :) ?

I mean using a library that overwrites Array prototype in a project that also uses playground.js

rezoner avatar Sep 02 '16 17:09 rezoner

Unfortunately it did! I'm writing a simple game for my current employer. We want to embed it on our main site - and this site uses a lot of different scripts. Some scripts are from our partners or are external libraries. And one of them used something like Array.prototype.remove = function(a, b) {.

I can't check all our libraries or do any change inside them, so I had to "fix" playground.js instead (and part of my game too cause I also used for ... in ;-) )

This "bug" I described didn't crash game - cause it just couldn't load one invalid "image" but still - error was there.

frondeus avatar Sep 02 '16 18:09 frondeus

Okay, is that notation important to you?

{ "a": "a.png" }

Because it contains key and path and I would like to use it so you can define what key you want to use to store some path.

rezoner avatar Sep 02 '16 18:09 rezoner

No, I don't use it. I just noticed that somebody can use it that way.

frondeus avatar Sep 02 '16 18:09 frondeus

Hey why not use something like this?

var keys = Object.keys(arg); // returns an array with the Keys of the object ex: ['a', 'b', 'c']
keys.forEach(function(key){
 arg[key] 
  // do something...
})

santiq avatar Sep 08 '16 14:09 santiq