今天,我们将弄清楚以下内容:什么是Array.isArray()方法,如何在后台工作,在ES6发布后发生了什么变化,为什么它对Array.prototype返回true,以及与此方法相关的更多主题。
自ECMAScript标准的第5版以来,已添加isArray()构造函数方法。在MDN网站上描述此方法的页面上,它说:Array
如果对象是数组,则Array.isArray()方法返回true;如果对象不是数组,则返回false。
确实,此方法非常适合测试不同的值以查看该值是否为数组。但是,它具有一项功能(如果没有它们,我们可以去哪里去)。如果传递此方法Array.prototype(它是一个对象),则将返回true。尽管事实是:
Array.prototype instanceof Array // false
Object.getPrototypeOf(Array.prototype) === Array.prototype // false
Array.prototype.isPrototypeOf(Array.prototype) // false
Array.prototype instanceof Object // true
Object.getPrototypeOf(Array.prototype) === Object.prototype // true
Object.prototype.isPrototypeOf(Array.prototype) // true
这种意外行为不仅会使普通的JavaScript程序员感到困惑,而且还会使经验丰富的战斗人员感到困惑。实际上,这促使我写这篇文章。有人可以将此行为与著名的JS功能进行比较:
typeof null === 'object' // true
但是,不必急于将此情况添加到wtfjs列表中,因为(突然)对此有一个逻辑解释。但是首先,让我们弄清楚为什么创建该方法isArray()以及隐藏在幕后的东西。
背景
ES5 , , instanceof.
[] instanceof Array // true
( ) prototype ( ). :
Object.getPrototypeOf([]) === Array.prototype // true
, (realm), , iframe, iframe (window). instanseof Array false, Array Array .
, , Array. , Object.prototype.toString() [[Class]] . :
function isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
, Array.
Array.isArray Array.prototype
ES6 . Arrray.prototype Object.prototype.toString() [object Array] :
Object.prototype.toString.call(Date.prototype) // [object Object]
Object.prototype.toString.call(RegExp.prototype) // [object Object]
1. false.
2. [[Class]] «Array» true.
3. false.
Object.prototype.toString(). , [[Class]] Array.prototype «Array»? ?
isArray() ES6. , , . ES6 [[Class]] Object.prototype.toString() -. :
…
3. O ToObject(this value).
4. isArray isArray(O).
5. isArray true, builtinTag «Array».
...
isArray() ES6 Array.isArray() . isArray() , , . true [[DefineOwnProperty]], ( length ).
Array.prototype , [[DefineOwnProperty]]. . . .
console.log(Array.prototype);
// [constructor: f, concat: f, ..., length: 0, ..., __proto__: Object]
. length, , (__proto__) Object. ! .
console.log(Object.getOwnPropertyDescriptor(Array.prototype, 'length'));
// {value: 0, writable: true, enumerable: false, configurable: false}
. length . . Array exotic object
console.log(Array.prototype.length); // 0
Array.prototype[42] = 'I\'m array';
Array.prototype[18] = 'I\'m array exotic object';
console.log(Array.prototype.length); // 43
Array.prototype.length = 20;
console.log(Array.prototype[42]); // undefined
console.log(Array.prototype[18]); // 'I\'m array exotic object'
, Array.prototype . ( ), prototype Array .
Array.prototype = new Array();
Object.assign(Array.prototype, {constructor() { ... }, concat() { ... }, ...});
Object.setPrototypeOf(Array.prototype, Object.prototype);
, , Array.prototype. , [[Class]] ( ) 'Array'.
Function, Date, RegExp
Date RegExp (Object), .. , .
Object.prototype.toString.call(Date.prototype); // [object Object]
Object.prototype.toString.call(RegExp.prototype); // [object Object]
Function.prototype . Object.prototype.toString()
Object.prototype.toString.call(Function.prototype); // [object Function]
, Function.prototype .
Function.prototype() // undefined;
)))
(Boolean, Number, String) Object.prototype.toString
Object.prototype.toString.call(Boolean.prototype); // [object Boolean]
Object.prototype.toString.call(Number.prototype); // [object Number]
Object.prototype.toString.call(String.prototype); // [object String]
. . [[Class]]
…
3. O ToObject(this value).
…
7. , O exotic String object builtinTag «String».
…
11. , O [[BooleanData]] builtinTag «Boolean».
12. , O [[NumberData]] builtinTag «Number».
)))
String.prototype + Number.prototype + Boolean.prototype // '0false'
(String.prototype + Boolean.prototype)[Number.prototype]; // 'f'
' ' + Number.prototype + Number.prototype + '7'; // ' 007'
Symbol.toStringTag
, Object.prototype.toString() ES6, Set, Symbol, Promise, :
Object.prototype.toString.call(Map.prototype); // [object Map]
Object.prototype.toString.call(Set.prototype); // [object Set]
Object.prototype.toString.call(Promise.prototype); // [object Promise]
Object.prototype.toString.call(Symbol.prototype); // [object Symbol]
, Object.prototype.toString, . , @@toStringTag. Object.prototype.toString(). , ES5 , , Set.prototype, Promise.prototype Set Promise .
, Object.prototype.toString().
Array.prototype ECMAScript . , , , Array.isArray() . , . ? - ?
- ES5 — 5- ESMAScript.
- ES6 — 6- ESMAScript.
- ECMAScript 6 | — , .
- Determining with absolute accuracy whether or not a JavaScript object is an array — , , Array.isArray .