Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript 判断是否为数组 #230

Open
toFrankie opened this issue Feb 26, 2023 · 0 comments
Open

JavaScript 判断是否为数组 #230

toFrankie opened this issue Feb 26, 2023 · 0 comments
Labels
2021 2021 年撰写 JS 与 JavaScript、ECMAScript 相关的文章

Comments

@toFrankie
Copy link
Owner

JavaScript 判断数组的几种方法及其利弊。

1. typeof

对于 Function、String、Number、Undefined 等几种类型的对象来说,他完全可以胜任。但是为 Array 时:

var arr = [1, 2, 3]
console.log(typeof arr) // "object"

// 同样的
console.log(typeof null) // "object"
console.log(typeof {}) // "object"

所以不能使用 typeof 来判断。

2. instanceof

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

var arr = [1, 2 ,3]
console.log(arr instanceof Array) // true

3. 原型链(constructor)

一般情况下,除了 undefinednull,其它都能使用 constructor 判断类型。

var arr = [1, 2, 3]
console.log(arr.__proto__.constructor === Array) // true
console.log(arr.constructor === Array) // true

// 注意:arr.__proto__ === Array.prototype 为 true。

但是某些情况下,判断是不准确的,比如:

// 构造函数
function Fn() {}
// 修改原型对象
Fn.prototype = new Array()
// 实例化对象
var fn = new Fn()

console.log(fn.constructor === Fn) // false
console.log(fn.constructor === Array) // true
// 此时的 fn 应该是一个普通对象,而非数组,所以此时使用 constructor 判断是不合适的。
使用 instanceof 和 constructor 的局限性:

使用和声明都必须是在当前页面,比如父页面引用了子页面,在子页面中声明了一个 Array,将其赋值给父页面的一个变量,那么此时做原型链的判断:Array === object.constructor 得到的是 false,原因如下:

  1. Array 属于引用型数据,在传递过程中,仅仅是引用地址的传递。
  2. 每个页面的 Array 原生对象所引用的地址是不一样的,在子页面声明的Array 所对应的构造函数是子页面的 Array 对象;父页面来进行判断,使用的 Array 并不等于子页面的 Array

附上 Categorizing values in JavaScript 的一段原话:
Array.isArray() exists because of one particular problem in browsers: each frame has its own global environment. An example: Given a frame A and a frame B (where either one can be the document). Code in frame A can pass a value to code in frame B. Then B code cannot use instanceof Array to check whether the value is an array, because its B Array is different from the A Array (of which the value could be an instance).

看代码:

var iframe = document.createElement('iframe')
document.body.appendChild(iframe)
var xArray = window.frames[window.frames.length - 1].Array
var xarr = new xArray()
var arr = new Array()

// 不同页面,结果并非我们所预期的 true,而是 false 哦!
console.log(xarr instanceof Array) // false
console.log(xarr.constructor === Array) // false

// 同页面才是 true 哦!
console.log(arr instanceof Array) // true
console.log(arr.constructor === Array) // true

4. Array.isArray

鉴于以上原因,ES5 标准提供的一个判断数组方法 isArray(),其原理也是通过 Object.prototype.toString() 判断对象的内部属性 [[Class]] 是否为 "Array",以达到判断数组的目的。

function isArray(arr) {
  return Array.isArray(arr)
}

5. Object.prototype.toString

所以,终极方法就是以下这个 👇

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

参考

@toFrankie toFrankie added the JS 与 JavaScript、ECMAScript 相关的文章 label Feb 26, 2023
@toFrankie toFrankie added the 2021 2021 年撰写 label Apr 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2021 2021 年撰写 JS 与 JavaScript、ECMAScript 相关的文章
Projects
None yet
Development

No branches or pull requests

1 participant