Heute werden wir Folgendes herausfinden: Was ist die Array.isArray () -Methode, wie funktioniert sie unter der Haube, was hat sich nach der Veröffentlichung von ES6 daran geändert, warum sie für Array.prototype true zurückgibt und viele weitere Themen im Zusammenhang mit dieser Methode.
Die isArray()Konstruktormethode Arraywurde seit der 5. Version des ECMAScript-Standards hinzugefügt . Auf der Seite, die diese Methode auf der MDN- Website beschreibt , heißt es:
Die Array.isArray () -Methode gibt true zurück, wenn das Objekt ein Array ist, und false, wenn es kein Array ist.
In der Tat eignet sich diese Methode gut zum Testen verschiedener Werte, um festzustellen, ob es sich bei dem Wert um ein Array handelt. Es hat jedoch eine Funktion (wohin können wir ohne sie gehen). Wenn Sie diese Methode übergeben Array.prototype, die ein Objekt ist, wird sie zurückgegeben true. Trotz der Tatsache dass:
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
Ein solches unerwartetes Verhalten kann nicht nur einen gewöhnlichen JavaScript-Programmierer, sondern auch einen erfahrenen Kämpfer verwirren. Eigentlich hat mich das dazu veranlasst, diesen Artikel zu schreiben. Jemand könnte dieses Verhalten mit einer berühmten JS-Funktion vergleichen:
typeof null === 'object' // true
Es besteht jedoch kein Grund zur Eile, diesen Fall zur wtfjs- Liste hinzuzufügen , da es (plötzlich) eine logische Erklärung dafür gibt. Aber zuerst wollen wir herausfinden, warum die Methode erstellt wurde isArray()und was sich unter der Haube verbirgt.
Hintergrund
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 .