¿Cómo puedo comprobar si un objeto es una matriz?

3095

Estoy tratando de escribir una función que acepte una lista de cadenas o una sola cadena. Si es una cadena, entonces quiero convertirla en una matriz con solo un elemento para poder recorrerla sin temor a un error.

Entonces, ¿cómo verifico si la variable es una matriz?

13
  • 8
    Pensé que querías 'verificar si el objeto es una matriz', pero quieres verificar si 'el objeto es una matriz de cadenas o una sola cadena' específicamente. ¿No estás seguro de verlo? O solo soy yo? Estaba pensando en algo más como esto ... ¿soy yo el que falta algo aquí? rr1g0 23/07/2015 a las 18:23
  • 164
    TL; DR - arr.constructor === Arrayes el más rápido. Neta 23/11/15 a las 22:37
  • 4
    jsben.ch/#/QgYAV - un punto de referencia para las formas más comunesEscapeNetscape 24 oct 2016 a las 17:34
  • 49
    TL; DR - Matriz. isArray (arr) desde ES5; y $. isArray (arr) en jQuery. Ondra Žižka 19/12/2016 a las 9:55
  • 7
    Solo tenga en cuenta que si por alguna razón sobrescribe su constructor a través del prototipo, esa arr.constructor === Arrayprueba devolverá falso. Array.isArray(arr)Sin embargo, todavía devuelve verdadero. ghaschel 23 feb 2018 a las 17:44
1381

En los navegadores modernos puede hacer:

Array.isArray(obj)

( Compatible con Chrome 5, Firefox 4.0, Internet Explorer 9, Opera 10.5 y Safari 5)

Para compatibilidad con versiones anteriores, puede agregar lo siguiente:

// Only implement if no native implementation is available
if (typeof Array.isArray === 'undefined') {
  Array.isArray = function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
  }
};

Si usa jQuery, puede usar jQuery.isArray(obj)o $.isArray(obj). Si usa Underscore.js , puede usar _.isArray(obj).

Si no necesita detectar matrices creadas en diferentes marcos, también puede usar instanceof:

obj instanceof Array
7
  • 11
    Aquí hay una lista más completa de navegadores que admitenArray.isArraylightswitch05 17 de diciembre de 2014 a las 18:51
  • if (typeof Array.isArray === 'undefined') {podría cambiarse aif(!Array.isArray) {iMatoria 21 de mayo de 2018 a las 4:38
  • Por lo que vale, Object.prototype.string.call(obj)se puede falsificar si el objeto lo tiene Symbol.toStringTag. Dicho esto, no tengo conocimiento de ningún entorno que envíe, Symbol.toStringTagpero no Array.isArraypor lo que parece seguro. Benjamin Gruenbaum 6/07/18 a las 10:27
  • 8
    ¿Por qué instanceof Arrayfalla si la matriz es de un marco diferente? NobleUplift 20/08/18 a las 21:45
  • 26
    @NobleUplift: instanceof Arrayfalla si la matriz es de un marco diferente porque cada matriz de ese marco diferente tiene un Arrayconstructor y prototipo diferente . Por razones de compatibilidad / seguridad, cada marco tiene su propio entorno global, y esto incluye objetos globales. Lo Objectglobal de un marco es diferente de lo Objectglobal de otro. Lo mismo Arrayocurre con los globales. Axel Rauschmayer habla más sobre esto . jschoi 22 de septiembre de 2018 a las 7:45
1976

El método dado en el estándar ECMAScript para encontrar la clase de Objeto es usar el toStringmétodo de Object.prototype.

if(Object.prototype.toString.call(someVar) === '[object Array]') {
    alert('Array!');
}

O puede usar typeofpara probar si es una cadena :

if(typeof someVar === 'string') {
    someVar = [someVar];
}

O si no está preocupado por el rendimiento, puede simplemente hacer concatuna nueva matriz vacía.

someVar = [].concat(someVar);

También está el constructor que puede consultar directamente:

if (somevar.constructor.name == "Array") {
    // do something
}

Echa un vistazo a un tratamiento completo del blog de TJ Crowder , como se publica en su comentario a continuación.

Consulte este punto de referencia para tener una idea de qué método funciona mejor: http://jsben.ch/#/QgYAV

Desde @Bharath , convierta una cadena en una matriz usando ES6 para la pregunta formulada:

const convertStringToArray = (object) => {
   return (typeof object === 'string') ? Array(object) : object
}

Suponer:

let m = 'bla'
let n = ['bla','Meow']
let y = convertStringToArray(m)
let z = convertStringToArray(n)
console.log('check y: '+JSON.stringify(y)) . // check y: ['bla']
console.log('check y: '+JSON.stringify(z)) . // check y: ['bla','Meow']
27
  • 67
    +1 Sí, toStringes una de las formas de hacerlo. Hago un pequeño resumen aquí: blog.niftysnippets.org/2010/09/say-what.htmlT.J. Crowder 23/01/11 a las 18:57
  • 4
    typeof new String('beans') > 'objeto'Ben 14 de agosto de 2012 a las 16:11
  • 17
    Si no desea escribir "[object Array]", use Object.prototype.toString.call (someVar) === Object.prototype.toString.call ([]) o cree una función conveniente para obtener el tipo si no no quiero escribir Object.prototype.toString.callPramod 15 de marzo de 2013 a las 6:15
  • 15
    Utilizo Vanilla Array.isArray que funciona en 'navegadores modernos' (es decir, IE9 + y todos los demás). Y para compatibilidad con navegadores antiguos, utilice la corrección de MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…David Gilbertson 11/10/2013 a las 4:40
  • 22
    Vivir en el mundo moderno -Array.isArray(obj)mcfedr 12/11/15 a las 23:53
1303

Primero verificaría si su implementación admite isArray:

if (Array.isArray)
    return Array.isArray(v);

También puede intentar usar el instanceofoperador

v instanceof Array
11
  • 130
    v instanceof Arraydevolverá falso si vse creó en otro marco ( ves una instancia de la thatFrame.contentWindow.Arrayclase). pepkin88 3 de enero de 2012 a las 2:08
  • 48
    Para ser específico: Array.isArrayse define como parte de ECMAScript 5 / Javascript 1.8.5. jevon 23/10/12 a las 5:38
  • 9
    Solución realmente simple y ordenada PERO isArray no es compatible con algunos navegadores más antiguos (por ejemplo, IE7 e IE8). Fuente: kangax.github.io/es5-compat-table/#Wookie88 1 de julio de 2013 a las 10:16
  • 3
    ¿Qué tal: si (Array.isArray) return Array.isArray (v); de lo contrario, devuelve la instancia de Array; lewdev 9 de enero de 2015 a las 23:05
  • 3
    o simplemente:return (Array.isArray && Array.isArray(v)) || (v instanceof Array);Stijn de Witt 12/07/2015 a las 14:29
304

jQuery también ofrece un $.isArray()método:

var a = ["A", "AA", "AAA"];

if($.isArray(a)) {
  alert("a is an array!");
} else {
  alert("a is not an array!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
6
  • 28
    Solo una nota, jQuery usa el método toString internamente: Fuente de GitHubJacob Squires 17 de abril de 2014 a las 1:25
  • 7
    @JacobSquires, depende. Acabo de probar aquí, el último jQuery en Chrome, $.isArray === Array.isArrayestá volviendo verdadero. Geeky Guy 22/10/2014 a las 14:12
  • 4
    @Renan: Esto es lo bueno de usar jQuery. Por lo general, utiliza el método más moderno y mejor para hacerlo, y no tiene que hacer todas las funciones comprobando usted mismo para saber qué usar. awe 2 dic 2015 a las 9:55
  • jQuery está usando Array.isArraydetrás de escena: github.com/jquery/jquery/blob/master/src/core.js#L211Sergiu 24/04/2016 a las 9:16
  • 3
    Pero nadie va a usar jQuery SÓLO PARA esta funcionalidad, ¿verdad? No solo descargaría jquery porque quiero verificar si algo es una matriz: pAutomagisch 17/02/2017 a las 13:46
108

Este es el más rápido entre todos los métodos (todos los navegadores son compatibles):

function isArray(obj){
    return !!obj && obj.constructor === Array;
}
10
  • 3
    Tienes razón, ese es el más rápido según las pruebas que incluí en la pregunta. mpen 6 dic.15 a las 21:59
  • 6
    ¿Hay inconvenientes en utilizar este método? Parece mucho más simple y eficaz que la respuesta superior aceptada. David Meza 26 de ene. De 2016 a las 18:35
  • @shinobi - solo por curiosidad (y lo he visto a menudo) - ¿por qué expresas la condición if (obj && Array === obj.constructor)en lugar de if (obj && obj.constructor === Array)? ¿Se pierde en la traducción al inglés y luego en codificar? Por ejemplo, los angloparlantes generalmente tienden a preguntar "¿existe el objeto y su constructor proviene de la clase de matriz?", por lo que el flujo de código al leerlo es más lógico. o hay alguna razón técnica? unsynchronized 26 de junio de 2016 a las 1:54
  • function object_type(o){var t = typeof(o);return ((t==="object") && (o.constructor===Array)) ? "array" : t;} /*allows you to */ switch(object_type(o)){ case 'array': break; case 'object' : o.dosomething();}unsynchronized 26 de junio de 2016 a las 6:10
  • 4
    @shinobi todo bien. Supongo que podría ser una resaca de un hábito seguro de c: si accidentalmente usa = en lugar de ==, no se compilaría ya que no es una variable asignable. unsynchronized 26 de junio de 2016 a las 6:35
50

Imagina que tienes esta matriz a continuación :

var arr = [1,2,3,4,5];

JavaScript (navegadores nuevos y antiguos):

function isArray(arr) {
  return arr.constructor.toString().indexOf("Array") > -1;
}

o

function isArray(arr) {
  return arr instanceof Array;
}

o

function isArray(arr) {
  return Object.prototype.toString.call(arr) === '[object Array]';
}

Entonces llámalo así:

isArray(arr);

JavaScript (Internet Explorer 9+, Chrome 5+, Firefox 4+, Safari 5+ y Opera 10.5+)

Array.isArray(arr);

jQuery:

$.isArray(arr);

Angular:

angular.isArray(arr);

Underscore.js y Lodash :

_.isArray(arr);
35

Array.isArray funciona rápido, pero no es compatible con todas las versiones de navegadores.

Por lo tanto, podría hacer una excepción para otros y usar un método universal:

    Utils = {};
    Utils.isArray = ('isArray' in Array) ?
        Array.isArray :
        function (value) {
            return Object.prototype.toString.call(value) === '[object Array]';
        }
5
  • 3
    Necesitas obtener el .toString()método de Object.prototype. Ahora mismo estás usando window.toString(), que no es lo mismo. the system 15 feb 2013 a las 18:00
  • Tienes razón. window.toStringhaga lo mismo que Object.prototype.toStringen Chrome. CruorVult 18 feb 2013 a las 11:17
  • isArray no es rápido en absoluto. Es el método más lento. jemiloii 12/12/14 a las 16:01
  • ¿Por qué no agregarlo a Array en lugar de a Utils? (Sé que no desea propiedades adicionales en nuevos objetos de matriz, pero creo que eso solo sucede si agrega isArray a Array.prototype)David Winiecki 13 de diciembre de 2014 a las 3:42
  • ¿Qué quiere decir con "método universal"? Peter Mortensen 12 de agosto a las 20:21
32

Una función simple para verificar esto:

function isArray(object)
{
    return object.constructor === Array;
}
10
  • 17
    Reduciría eso a una línea return object.constructor === Array, pero ¿estás seguro de que esto solo devolverá verdadero para las matrices? mpen 4 de septiembre de 2012 a las 18:39
  • 13
    Puede hacer eso con todas las expresiones booleanas. Me if(x) return true; else return falsevuelve loco cuando veo :-) Incluso si está al revés, debes negar la expresión. mpen 4 de septiembre de 2012 a las 18:52
  • 4
    La razón por la que esto no devuelve verdadero para getElementsByTagName, es porque el resultado de esa función es en realidad una HTMLCollection y no una matriz. Yuval A. 4 dic 14 a las 17:35
  • 8
    Esto falla gravemente si el objeto no está definido o es nulo. John Henckel 20/03/15 a las 15:58
  • 2
    @JohnHenckel Vea mi respuesta stackoverflow.com/a/29400289/34806 tiene en cuenta tanto su preocupación como el primer comentario, todo en una líneaDexygen 1/04/15 a las 20:37
19

Solo hay una solución de línea para esta pregunta

x instanceof Array

donde x es la variable, devolverá verdadero si x es una matriz y falso si no lo es.

3
  • ¡Mucho más limpio y seguro para el futuro! Esto o una typeofcomparación. ChristoKiwi 16 de junio de 2017 a las 1:38
  • ¿Es esto algo que recibe una buena cantidad de soporte del navegador? Me gusta. Dan Zuzevich 20/08/2017 a las 12:11
  • 3
    Desafortunadamente, esto no es realmente útil sin un try / catch porque si "x" es un objeto como {}una matriz, entonces obtendrá un error de sintaxis. abalter 27/04/18 a las 5:24
18

Como dice MDN aquí :

use Array.isArray or Object.prototype.toString.call to differentiate regular objects from arrays

Como esto:

  • Object.prototype.toString.call(arr) === '[object Array]', o

  • Array.isArray(arr)

dieciséis

Puede verificar el tipo de su variable si es una matriz con;

var myArray=[];

if(myArray instanceof Array)
{
....
}
1
  • 2
    Algunas personas ya lo han mencionado instanceof... Creo que falla en algunos escenarios extraños. mpen 15 de enero de 2013 a las 16:30
dieciséis

Haría una función para probar el tipo de objeto con el que estás tratando ...

function whatAmI(me){ return Object.prototype.toString.call(me).split(/\W/)[2]; }

// tests
console.log(
  whatAmI(["aiming","@"]),
  whatAmI({living:4,breathing:4}),
  whatAmI(function(ing){ return ing+" to the global window" }),
  whatAmI("going to do with you?")
);

// output: Array Object Function String

entonces puedes escribir una simple declaración if ...

if(whatAmI(myVar) === "Array"){
    // do array stuff
} else { // could also check `if(whatAmI(myVar) === "String")` here to be sure
    // do string stuff
}
0
14

Hago esto de una manera muy sencilla. Esto funciona para mi.

Array.prototype.isArray = true;

a=[]; b={};
a.isArray  // true
b.isArray  // (undefined -> false)
2
  • 9
    engañado por{isArray:true}Bergi 7 de agosto de 2015 a las 7:17
  • JSON.parse(someDataFromElsewhere).items.isArraypodría devolver verdadero (dependiendo de los datos) y romper su código. Roy Tinker 19/12/2016 a las 20:52
13

Este es mi intento de mejorar esta respuesta teniendo en cuenta los comentarios:

var isArray = myArray && myArray.constructor === Array;

Se deshace del if / else y tiene en cuenta la posibilidad de que la matriz sea nula o indefinida

1
  • constructor no está disponible en ES5TechTurtle 21/02/2017 a las 17:37
12

He actualizado el violín jsperf con dos métodos alternativos, así como con la comprobación de errores.

Resulta que el método que define un valor constante en los prototipos 'Objeto' y 'Matriz' es más rápido que cualquiera de los otros métodos. Es un resultado algo sorprendente.

/* Initialisation */
Object.prototype.isArray = function() {
  return false;
};
Array.prototype.isArray = function() {
  return true;
};
Object.prototype._isArray = false;
Array.prototype._isArray = true;

var arr = ["1", "2"];
var noarr = "1";

/* Method 1 (function) */
if (arr.isArray()) document.write("arr is an array according to function<br/>");
if (!noarr.isArray()) document.write("noarr is not an array according to function<br/>");
/* Method 2 (value) - **** FASTEST ***** */
if (arr._isArray) document.write("arr is an array according to member value<br/>");
if (!noarr._isArray) document.write("noarr is not an array according to member value<br/>");

Estos dos métodos no funcionan si la variable toma el valor indefinido, pero funcionan si está seguro de que tienen un valor. Con respecto a verificar teniendo en cuenta el rendimiento si un valor es una matriz o un valor único, el segundo método parece un método rápido válido. Es un poco más rápido que 'instanceof' en Chrome, dos veces más rápido que el segundo mejor método en Internet Explorer, Opera y Safari (en mi máquina).

12

Sé que la gente está buscando algún tipo de enfoque de JavaScript sin formato. Pero si quiere pensar menos en ello, eche un vistazo a isArray de Underscore.js :

_.isArray(object)

Devuelve verdadero si el objeto es una matriz.

(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true
1
  • 8
    "A menos que también se incluya otra etiqueta para un marco / biblioteca, se espera una respuesta de JavaScript pura". Michał Perłakowski 9 de enero de 2016 a las 21:53
12

Array.isArray ()

Array.isArray = Array.isArray || function (vArg) {
    return Object.prototype.toString.call(vArg) === "[object Array]";
};
1
  • ¿Puedes elaborar un poco? Por ejemplo, ¿por qué está "Array.isArray" en ambos lados de "="? "Array.isArray" es un método. ¿Cuál es el principio de funcionamiento? Responda editando (cambiando) su respuesta , no aquí en los comentarios ( sin "Editar:", "Actualizar:" o similar; la respuesta debería aparecer como si estuviera escrita hoy). Peter Mortensen 12 de agosto a las 20:26
7

La mejor práctica es compararlo usando constructoralgo como esto

if(some_variable.constructor === Array){
  // do something
}

También puede usar otros métodos, como typeOfconvertirlo en una cadena y luego compararlo, pero compararlo con dataType siempre es un mejor enfoque.

5

Si los únicos dos tipos de valores que se pueden pasar a esta función son una cadena o una matriz de cadenas, manténgalo simple y use una typeofverificación para la posibilidad de cadena:

function someFunc(arg) {
    var arr = (typeof arg == "string") ? [arg] : arg;
}
1
  • Sí ... eso funcionaría para este escenario, pero no en general. Terminé usando varargs de todos modos. :)mpen 23/01/11 a las 20:01
5

Aquí está mi enfoque perezoso:

if (Array.prototype.array_ === undefined) {
  Array.prototype.array_ = true;
}

// ...

var test = [],
    wat = {};

console.log(test.array_ === true); // true
console.log(wat.array_ === true);  // false

Sé que es un sacrilegio "meterse con" el prototipo, pero parece funcionar significativamente mejor que el toStringmétodo recomendado .

Nota: Una trampa de este enfoque es que no funcionará más allá de los iframelímites , pero para mi caso de uso, esto no es un problema.

7
  • 1
    ya no es mejor en términos de rendimiento, al menos en FF30 en Ubuntu de 64 bitstest30 21/07/2014 a las 9:40
  • 2
    engañado por los wat = {array_: true}objetos. Bergi 7 de agosto de 2015 a las 7:18
  • @Bergi: Sí, eso debería ser obvio. Si estás estableciendo obj.array_ = true, entonces solo te estás engañando a ti mismo . namuol 7 de agosto de 2015 a las 23:56
  • @namuol: No necesariamente me estoy engañando. A menudo se utilizan suficientes objetos como diccionarios. Piense en un cacheobjeto para memorizar los resultados de la búsqueda que utiliza las cadenas de búsqueda como claves de propiedad. ¿Qué pasa si un usuario busca array_? ¿Su objeto se convierte en una matriz debido a eso? Es solo un error. Bergi 8 de agosto de 2015 a las 16:15
  • @namuol: Además, este enfoque requeriría que todas las partes involucradas (incluidas las bibliotecas usadas) puedan acordar que .array_se usa para etiquetar matrices. Ese no es realmente el caso aquí, .arraypuede significar cualquier cosa. Debería utilizar al menos una cadena descriptiva y señalar que el uso arbitrario no es apropiado, por ejemplo, con .__isArray = true. Bergi 8 de agosto de 2015 a las 16:19
5

Esta función convertirá casi cualquier cosa en una matriz:

function arr(x) {
    if(x === null || x === undefined) {
        return [];
    }
    if(Array.isArray(x)) {
        return x;
    }
    if(isString(x) || isNumber(x)) {
        return [x];
    }
    if(x[Symbol.iterator] !== undefined || x.length !== undefined) {
        return Array.from(x);
    }
    return [x];
}

function isString(x) {
    return Object.prototype.toString.call(x) === "[object String]"
}

function isNumber(x) {
    return Object.prototype.toString.call(x) === "[object Number]"
}

Utiliza algunas funciones de navegador más nuevas, por lo que es posible que desee rellenar esto para obtener el máximo soporte.

Ejemplos:

> arr(null);
[]
> arr(undefined)
[]
> arr(3.14)
[ 3.14 ]
> arr(1/0)
[ Infinity ]
> gen = function*() { yield 1; yield 2; yield 3; }
[Function: gen]
> arr(gen())
[ 1, 2, 3 ]
> arr([4,5,6])
[ 4, 5, 6 ]
> arr("foo")
[ 'foo' ]

Las cadenas de NB se convertirán en una matriz con un solo elemento en lugar de una matriz de caracteres. Elimine el isStringcheque si lo prefiere al revés.

Lo he usado Array.isArrayaquí porque es el más robusto y también el más simple.

5

Lo siguiente podría usarse si sabe que su objeto no tiene un método concat.

var arr = [];
if (typeof arr.concat === 'function') {
    console.log("It's an array");
}
1
  • Este es un buen truco, pero podría anularse ... pero la mayoría de las veces debería obtener el resultadoAlireza 9/04/2017 a las 13:23
5
var a = [], b = {};

console.log(a.constructor.name == "Array");
console.log(b.constructor.name == "Object");
1
  • 1
    Hola, gracias por su respuesta. Las respuestas de solo código tienden a pasarse por alto, ¿le importaría agregar alguna explicación a su código? giraffesyo 30/12/19 a las 17:12
5

La mejor solución que he visto es un reemplazo de varios navegadores para typeof. Compruebe la solución de Angus Croll .

La versión TL; DR está a continuación, pero el artículo es una gran discusión sobre el tema, por lo que debería leerlo si tiene tiempo.

Object.toType = function(obj) {
    return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
}
// ... and usage:
Object.toType([1,2,3]); //"array" (all browsers)

// or to test...
var shouldBeAnArray = [1,2,3];
if(Object.toType(shouldBeAnArray) === 'array'){/* do stuff */};
5

Hay un buen ejemplo en el libro JavaScript Patterns de Stoyan Stefanov que se supone que maneja todos los problemas posibles así como también usa el método ECMAScript 5 Array.isArray () .

Asi que aqui esta:

if (typeof Array.isArray === "undefined") {
    Array.isArray = function (arg) {
        return Object.prototype.toString.call(arg) === "[object Array]";
    };
}

Por cierto, si está usando jQuery, puede usar su método $ .isArray () .

1
  • 2
    +1: ¿por qué no simplemente un simple if(!Array.isArray) {...? Marco Demaio 18/02/2014 a las 14:49
5

Podría usar el método isArray , pero preferiría verificar con:

Object.getPrototypeOf(yourvariable) === Array.prototype

3
  • ¿Por qué preferirías esto? mpen 28/02/18 a las 17:36
  • @mpen Object.getPrototypeOf(yourvariable)devuelve el prototipo de un objeto Array. Y el código es más rápido y seguro de usar. STEEL 1 de marzo de 2018 a las 10:32
  • 1
    Es fácil de frustrar: pastebin.com/MP8d5bCE Además, ¿tiene pruebas de rendimiento para respaldar su afirmación de "más rápido"? mpen 1 de marzo de 2018 a las 23:11
4
function isArray(value) {
    if (value) {
        if (typeof value === 'object') {
            return (Object.prototype.toString.call(value) == '[object Array]')
        }
    }
    return false;
}

var ar = ["ff","tt"]
alert(isArray(ar))
1
  • Una explicación estaría en orden. Responda editando (cambiando) su respuesta , no aquí en los comentarios ( sin "Editar:", "Actualizar:" o similar; la respuesta debería aparecer como si estuviera escrita hoy). Peter Mortensen 12 de agosto a las 20:30
4

Una función simple para probar si un valor de entrada es una matriz es la siguiente:

function isArray(value)
{
  return Object.prototype.toString.call(value) === '[object Array]';
}

Esto funciona en todos los navegadores y con navegadores más antiguos. Esto se extrajo de la publicación del blog de TJ Crowders

1
  • 1
    El enlace aún funciona en 2021.Peter Mortensen 12 de agosto a las 20:33
4

Puedes probar esto:

var arr = []; (or) arr = new Array();
var obj = {}; (or) arr = new Object();

arr.constructor.prototype.hasOwnProperty('push') //true

obj.constructor.prototype.hasOwnProperty('push') // false
0
4

En su caso, puede usar el concatmétodo de Array que puede aceptar objetos individuales, así como una matriz (e incluso combinada):

function myFunc(stringOrArray)
{
  var arr = [].concat(stringOrArray);

  console.log(arr);

  arr.forEach(function(item, i)
  {
    console.log(i, "=", item);
  })
}

myFunc("one string");

myFunc(["one string", "second", "third"]);

concat parece ser uno de los métodos más antiguos de Array (incluso IE 5.5 lo conoce bien).