我正在尝试编写一个函数,它要么接受字符串列表,要么接受单个字符串。如果它是一个字符串,那么我想把它转换成一个只有一个项的数组,这样我就可以在上面循环,而不用担心出错。
那么如何检查变量是否为数组?
我正在尝试编写一个函数,它要么接受字符串列表,要么接受单个字符串。如果它是一个字符串,那么我想把它转换成一个只有一个项的数组,这样我就可以在上面循环,而不用担心出错。
那么如何检查变量是否为数组?
当前回答
在您的情况下,您可以使用Array的concat方法,它可以接受单个对象,也可以接受数组(甚至组合):
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似乎是Array最古老的方法之一(即使是IE 5.5也很熟悉)。
其他回答
我见过的最佳解决方案是用跨浏览器替换typeof。检查Angus Croll的解决方案。
TL;DR版本在下面,但这篇文章对这个问题进行了很好的讨论,所以如果您有时间,应该阅读它。
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 */};
我知道,人们正在寻找某种原始的JavaScript方法。但如果你想少想一想,看看Undercore.js的isArray:
_.isArray(object)
如果对象是数组,则返回true。
(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true
首先,您可以检查console.log(对象类型)。
如果输出是对象,则var{data}=对象,即根据对象键销毁对象。
函数可以是这样的:
const abc = (str1, str2=null) => {
var result = [];
result.push(str1);
result.push(str2);
return result.join("");
}
Array.isArray是实现这一点的方法。例如:
var arr = ['tuna', 'chicken', 'pb&j'];
var obj = {sandwich: 'tuna', chips: 'cape cod'};
// Returns true
Array.isArray(arr);
// Return false
Array.isArray(obj);
幸运的是,ECMAScript 5在2009年12月引入了Array.isArray()。如果出于某种原因,您使用的JavaScript版本早于ECMAScript 5,请升级。
但是,如果您坚持使用它,那么数组确实具有某些财产,可以将它们与任何其他类型区分开来。我在其他任何答案中都没有提到过的财产。让我们进入一些JavaScript政治。
数组是一个对象(typeof[]==“object”),但与传统对象不同,它们具有长度属性(typeof({}).length==“undefined”)。null也是一个对象(typeof null==“object”),但不能访问null属性,因为null不是对象。
这是规范中的一个bug,可以追溯到JavaScript的最开始,当时对象的类型标记为0,null表示为文本null指针0x00,这导致解释器将其与对象混淆。
不幸的是,这不能解释[]与{length:0}之间的关系。所以我们现在必须转向原型链。
( [] ).__proto__==阵列原型&&([])__原型__!==Object.prototype。
因此,如果没有Array.isArray(),这几乎是我们能得到的最接近的结果:
function is_array(array){
return array !== null
&& typeof array === "object"
&& array.__proto__ === Array.prototype;
}
[ [], [1,2,3], {length: 0}, {},
1, 0, Infinity, NaN, "1", "[1,2,3]",
null, undefined, [null], [undefined], {a:[]},
[{}], [{length: 0}], [Infinity], [NaN],
{__proto__: Array.prototype}
].filter(is_array)
// Expected: [ [], [1,2,3], [null], [undefined], [{}], [{length: 0}], [Infinity], [NaN] ]
// Actual: [ [], [1,2,3], [null], [undefined], [{}], [{length: 0}], [Infinity], [NaN], {__proto__: Array.prototype} ]
被恶意设计成看起来像数组的对象实际上通过了图灵测试。然而,用Array原型链替换原型链就足以使其像数组一样,有效地使其成为数组。
世界上唯一能告诉这样的对象实际上不是数组的是array.isArray()。但出于通常检查对象是否是数组的目的,所述对象应该在代码中表现良好。
甚至当你人为地改变数组长度时的行为也是一样的:如果长度比数组中的元素数长,你会有一个特殊的“隐式未定义”类型的“空槽”,这种类型在某种程度上不同于未定义,同时也是==未定义的;这就是我们使用typeof obj的原因!==“undefined”以避免引发ReferenceError,因为obj==undefineed仅在obj被显式定义为undefine时才会引发错误。
a = {__proto__: Array.prototype}; // Array {}
a.push(5)
a // [5]
a.length = 5
a // [5, empty x 4]
b = a.map(n => n*n) // [25, empty x 4]
b.push(undefined)
b.push(undefined)
b // [25, empty x 4, undefined, undefined]
b[1] // undefined
b[1] === b[5] // true
Array.isArray(a) // false
Array.isArray(b) // true
不过,不要使用is_array()。为了学习目的重新发明轮子是一回事。在生产代码中这样做是另一回事。甚至不要将其用作polyfill。支持旧JavaScript版本意味着支持旧浏览器意味着鼓励使用不安全的软件意味着用户面临恶意软件的风险。