javascript判断一个对象是否为数组

javascript判断一个对象是否为数组

大家好,又见面了,我是全栈君。

在JavaScript中,可以通过typeof操作符来判断基本数据类型(Undefined、Null、Boolean、Number和String),同时相信大家也熟知typeof对于对象的判断是不准确的,因为特殊值Null被认为是一个空的对象的引用。

对于数组的创建,可以使用构造函数,通过传递数量

var colors = new Array(3);

也可以在构造函数中传递值来创建数组

var colors = new Array('red', 'blue', 'green');

创建数组的第二种基本方法是使用数组字面量

var colors = ['red', 'blue', 'green'];

判断一个对象是否为数组,最先想到的就是instanceof操作符,通过判断对象是否为Array的实例来达到目的

var array = [];
console.log(array instanceof Array); // true

使用instanceof操作符的问题在于它假定只有一个全局执行环境。

然而这在某些特殊环境下并不安全,下面引用自MDN:

在浏览器中,我们的脚本可能需要在多个窗口之间进行交互。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。这可能会引发一些问题。比如,表达式 [] instanceof window.frames[0].Array 会返回false,因为Array.prototype !== window.frames[0].Array.prototype

因此,需要另寻别的方法来判断。

大家知道在任何值上调用Object原生的toString()方法,都会返回一个[object NativeConstructorName]格式的字符串。

var colors = [];
console.log(Object.prototype.toString.call(colors)); // "[object Array]"

利用这一点我们可以进一步将其封装成一个通用函数

function isArray(value) {
  return Object.prototype.toString.call(value).slice(8, -1) === 'Array';
}

在ES5中,为了解决这个问题,提供了Array.isArray()方法来确定某个值到底是不是数组,而不管它是在哪个全局作用域中创建的。

var colors = [];
console.log(Array.isArray(colors)); // true

行文到此应该结束了,因为判断数组的方法其实没有什么好说的。但是在ES6中,由于增加了一种新数据类型Symbol,并通过Symbol暴露了一些内部操作,导致了在判断的结果上会出现一些不确定情况。

和本文相关的一个是Symbol.hasInstance方法,它是执行操作符instanceof时内部调用的方法,用于检测对象的继承信息。当我们调用colors instanceof Array时,实际上调用的是Array[Symbol.hasInstance](colors)

如果没有了解过Symbol的童鞋还不清楚这意味着什么,且看下面的例子:

var sameArray = {
  [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}

console.log([] instanceof sameArray); // true

这里我们定义了sameArrayinstance行为,内部调用了Array.isArray()方法来判断传入的参数是否为一个数组。同样我们可以改变一个classinstanceof行为,这里需要注意一点的是在class中是作为类的静态方法。

class Person {
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}

最重要的是我们可以直接改变内置Array的instanceof行为,导致其完全不可靠。

var colors = [];
Object.defineProperty(Array, Symbol.hasInstance, {
  value(v) {
    return false;
  }
})
console.log(colors instanceof Array); // false
console.log(Array.isArray(colors)); // true

上面我们提到使用Object原生的toString()方法来判断值是否为数组的实例。这在ES5中是一个很有效的方式,但在ES6中我们同样可以通过Symbol.toStringTag来改变Object.prototype.toString()的默认值。

Array.prototype[Symbol.toStringTag] = 'Magic';
var colors = [];
console.log(Object.prototype.toString.call(colors)); // "[object Magic]"

这也意味着Object.prototype.toString()不是一个十分可靠的识别对象类型的方式。

注意:虽然语言本身不会阻止你使用Symbol.toStringTag属性来改变对象内建的toString()方法的默认值,但还是不建议这样做。

最后:不论是在ES5还是ES6中,最可靠和最安全的数组判断方法是使用原生的Array.isArray()方法,而在ES3中我们可以直接使用Object.prototype.toString()来达到数组识别的目的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/108170.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 剑指Offer面试题:13.合并两个排序的链表

    一题目:合并两个排序的链表二代码实现将链表换成数组做简单的循环和递归测试(1)循环实现(2)递归实现

    2021年12月19日
    35
  • 量化投资学习——多因子权重组合优化问题

    量化投资学习——多因子权重组合优化问题关于多因子权重组合优化问题,这里首先整理若干链接供大家参考:pythonoptimize_Python与量化多因子——因子权重优化文章中从常见的因子合成方法,如静态权重,动态权重出发,拓展到了动态权重,介绍了最大化ICIR的缺点,介绍了cvxpy等工具包,包括常见的一些约束问题,文章还举了若干例子,比较好…

    2022年9月28日
    6
  • 人脸识别系统如何建模_3dmax人脸建模

    人脸识别系统如何建模_3dmax人脸建模本发明涉及生物特征识别,特别是涉及人脸识别中的特征建模方法。背景技术:人脸识别技术一般包括四个组成部分,分别为人脸图像采集、人脸图像预处理、人脸图像特征提取以及匹配与识别,具体来说:人脸图像采集及检测是指通过摄像镜头等视频图像采集装置采集包括有人脸的视频或图像数据,可以是采集对象的静态图像、动态图像、不同的位置、不同表情等。人脸图像预处理是指从采集的图像数据中确定人脸的部分,并进行灰度校正、噪声过…

    2025年12月10日
    4
  • ExtJS入门教程03,form中怎能没有validation[通俗易懂]

    ExtJS入门教程03,form中怎能没有validation[通俗易懂]接上篇内容,我们在学会extjsform的基本用法之后,今天我们来看看extjsform的validation功能。必填项,就是不能为空(allowBlank)效果:代码:{xtype:”textfield”,name:”UserName”,fieldLabel:”用户名”,allowBlank:false,…

    2025年6月18日
    4
  • html怎么使表格居中,html怎么使表格居中[通俗易懂]

    html怎么使表格居中,html怎么使表格居中[通俗易懂]回答:HTML中两个表格间的距离调整有两种适合微调的办法:1.设置第一个tbale的margin-bottom属性。例如:表示table表格底部保持100px间距。2.设置第二个tbale的margin-top属性。例如:表示table表格顶部保持100px间距。扩展知识margin属性可以单独改变元素(元素可以是表格或者DIV)的上,下,左,右边距。也可以一次改变所有的属性。margin属性…

    2026年1月24日
    7
  • Golang开发环境搭建(Windows)[通俗易懂]

    Golang开发环境搭建(Windows)[通俗易懂]golang下载地址:Downloads-TheGoProgrammingLanguage1)下载安装包安装2)环境变量配置:path:C:\Go\bin可执行文件路径加到环境变量path中 GOROOT:go的安装路径。C:\Go,官方包路径根据这个设置自动匹配 GOPATH:goinstall你的子包。有利于gobuild的时间配置集成开发环境1)IntellIJidea:安装go插件搜索不到go,配置管…

    2022年10月7日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号