14

I'm running the following code on Webkit:

var scriptElements = document.scripts;
var scriptUrls = [];
// URL matching
var regexp = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i;
for (var i = 0; i < scriptElements.length; i++) {
    element = scriptElements[i];
    var urls = element.innerHTML.match(regexp);
    console.log('local', urls);
    scriptUrls.concat(urls);
    console.log('global', scriptUrls);
}

I see non-empty arrays printed after 'local' but the 'global' always stays as an empty array. What's going on?

  • 4
    http://stackoverflow.com/questions/12803604/javascript-array-concat-not-working-why , http://stackoverflow.com/questions/3975170/javascript-how-to-join-combine-two-arrays-to-concatenate-into-one-array?rq=1 –  Oct 10 '12 at 00:47

2 Answers2

58

.concat creates a new Array. You need to overwrite the old one.

scriptUrls = scriptUrls.concat(urls);

Or if you want to keep the original scriptUrls Array, you can .push() the values in.

scriptUrls.push.apply(scriptUrls, urls);

This uses .apply() to convert urls into individual arguments passed to .push(). This way the content of urls is added to scriptUrls as individual items.


Also, note that .concat() flattens the Array. If you wanted an Array of Arrays, then you'd use scriptUrls.push(urls).

I Hate Lazy
  • 47,415
  • 13
  • 86
  • 77
  • 1
    That's right, people often misunderstand JS in this aspect. Most array and string methods require an assignment to make the changes, such as `replace` or `concat` but other's don't such as `splice` for example. – elclanrs Oct 10 '12 at 00:40
  • 1
    @user1689607 - Yup, realized that about 10 seconds after I posted my comment. – FrankieTheKneeMan Oct 10 '12 at 00:42
  • @elclanrs: I agree. I think `.splice` and `.reverse` are the only Array methods that modify the original. And no String methods do of course since strings are immutable. – I Hate Lazy Oct 10 '12 at 00:42
  • Nowadays there's `scriptUrls.push(...urls);` rather than `.push.apply`. See [here](https://stackoverflow.com/a/73570026/6243352) for a thorough explanation. – ggorlen Sep 01 '22 at 13:30
2

concat does not alter this or any of the arrays provided as arguments but instead returns a "one level deep" copy that contains copies of the same elements combined from the original arrays.

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/concat

spender
  • 117,338
  • 33
  • 229
  • 351