string.match() returns a String instead of an Array

Elie Zgala

I've been using Javascript string.match(*regex*) function to parse the navigator.userAgent string.

FYI, According to MDN & W3schools:

"The match() method searches a string for a match against a regular expression, and returns the matches, as an Array object."

I first parse once to get the wanted strings for the base string:

var userAgent = navigator.userAgent;
var splitted = userAgent.match(/[(][^)]+[)]|\w+\/\S+/ig);

Which gives me the following Output (Which is an Array)

Mozilla/5.0
(Macintosh; Intel Mac OS X 10_10_3)
AppleWebKit/537.36
(KHTML, like Gecko)
Chrome/41.0.2272.76
Safari/537.36

Then i parse the Navigator/Version type strings in a for loop

for (var i = 0; i < splitted.length; i++ ) {
    var str = splitted[i];
    if (str[0] == '(') {
    } else {
        var name = str.match(/[^\/]+/i);
        var version = str.match(/[0-9|\.]+/i);
}

But, very surprisingly and even though I get the desired result, I get a String Object for the name and an Array Object for the version

How is it even possible ?

Here's the snippet of the code (fiddle):

var userAgent = navigator.userAgent;
var splitted = userAgent.match(/[(][^)]+[)]|\w+\/\S+/ig);
var outputDiv = document.getElementById("log");

for (var i = 0; i < splitted.length; i++ ) {
  var str = splitted[i];
  if (str[0] == '(') {
  } else {
    var name = str.match(/[^\/]+/i);
    var version = str.match(/[0-9|\.]+/i);
    outputDiv.innerHTML += name.toString() + " is a " + typeof(name) + "<br>";
    outputDiv.innerHTML += version.toString() + " is a " + typeof(version) + "<br>";
  }
};
<div id="log"></div>

--- UPDATE ---

Thanks FactoryAidan for the answer, it was a scope problem.

Conclusion: be careful when naming global variables :)

FactoryAidan

Global Variable Scope

It is because you are using name as your variable. This is a global browser window variable that is inherently a string and cannot be stored as an Array

Even if you redeclare it with var name =, you are still in the global scope. And thus name (aka window.name) simply retains the last value you assign to it.

You can test this with the following on an empty page without defining any variables at all:

console.log(name===window.name) // Returns true
console.log(name,window.name)   // Returns 'Safari Safari' for my browser

Change name to something else

If you change your name variable to simply have a different name, like my_name, it stores the result of .match() as an Array.

var my_name = str.match(/[^\/]+/i);
var version = str.match(/[0-9|\.]+/i);

console.log(typeof my_name, my_name instanceof Array) // Returns object, true

Change Scope by wrapping in a function

This is your exact code wrapped inside a function and returns the correct variable types:

function getBrowserStuff(){

    var userAgent = navigator.userAgent;
    var splitted = userAgent.match(/[(][^)]+[)]|\w+\/\S+/ig);

    for (var i = 0; i < splitted.length; i++ ) {
        var str = splitted[i];
        if (str[0] == '(') {
        } else {
            var name = str.match(/[^\/]+/i);
            var version = str.match(/[0-9|\.]+/i);
            console.log('Name','Typeof '+(typeof name), 'IsArray '+(name instanceof Array),name)
            console.log('Version','Typeof '+(typeof version),'IsArray '+(version instanceof Array),version)
        }
    }

    return 'whatever'
}

getBrowserStuff()

Changing the variable name to my_name OR wrapping code like the above function returns this:

Name    Typeof object IsArray true ["Mozilla"]
Version Typeof object IsArray true ["5.0"]
Name    Typeof object IsArray true ["AppleWebKit"]
Version Typeof object IsArray true ["600.3.18"]
Name    Typeof object IsArray true ["Version"]
Version Typeof object IsArray true ["8.0.3"]
Name    Typeof object IsArray true ["Safari"]
Version Typeof object IsArray true ["600.3.18"]

Where before it returned this:

Name    Typeof string IsArray false Mozilla
Version Typeof object IsArray true  ["5.0"]
Name    Typeof string IsArray false AppleWebKit
Version Typeof object IsArray true  ["600.3.18"]
Name    Typeof string IsArray false Version
Version Typeof object IsArray true  ["8.0.3"]
Name    Typeof string IsArray false Safari
Version Typeof object IsArray true  ["600.3.18"]

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Why String.prototype.match() returns null instead of empty array?

RestAssured returns array instead of String

Protractor - getText() returns an Array instead of a String

Why StreamReader returns string instead of byte array

Sphinx returns digits instead of string in matches array

'this' returns array instead of a string. JavaScript

Select-Object -Unique returns String instead of String array

String match function returns an array, but if converted to number, returns the matched number

Match returns empty string

Loop array returns element of type string instead of array's type

Why Object.keys is returns array of string instead of array of Numbers

yq array manipulation returns string literal instead of an array

String split returns an array with two elements instead of one

Calling .text() with JQuery class selector returns one string instead of array

IE returns viewScope variable as string instead of array in XPage

Function returns string instead of dictionary

getResource returns boolean instead String[]

How to match string to array of string

Get an array instead of string

Return Array Instead of String

Function returns an instance of Future<String> instead of String

search in array for string match

Partial string match in array

Match a string with an array

Match string to array

Returning Flux<String> from Spring WebFlux returns one string instead of array of strings in JSON

Using char array instead of String

make array instead string in php

Pandas strptime returns a string instead of DateTime object