PHP's is_array in JavaScript

How to use

You you can install via yarn add locutus and require this function via const is_array = require('locutus/php/var/is_array').

It is important to use a bundler that supports tree-shaking so that you only ship the functions that you actually use to your browser, instead of all of Locutus, which is massive. Examples are: Parcel, webpack, or rollup.js. For server-side use this is typically less of a concern.

Examples

Please note that these examples are distilled from test cases that automatically verify our functions still work correctly. This could explain some quirky ones.

#codeexpected result
1is_array(['Kevin', 'van', 'Zonneveld'])true
2is_array('Kevin van Zonneveld')false
3is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'})true
4ini_set('locutus.objectsAsArrays', 0) is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'})false
5is_array(function tmp_a (){ this.name = 'Kevin' })false

Notes

  • In Locutus, javascript objects are like php associative arrays, thus JavaScript objects will also return true in this function (except for objects which inherit properties, being thus used as objects), unless you do ini_set(‘locutus.objectsAsArrays’, 0), in which case only genuine JavaScript arrays will return true

Here’s what our current JavaScript equivalent to PHP's is_array looks like.

module.exports = function is_array(mixedVar) {
// discuss at: https://locutus.io/php/is_array/
// original by: Kevin van Zonneveld (https://kvz.io)
// improved by: Legaev Andrey
// improved by: Onno Marsman (https://twitter.com/onnomarsman)
// improved by: Brett Zamir (https://brett-zamir.me)
// improved by: Nathan Sepulveda
// improved by: Brett Zamir (https://brett-zamir.me)
// bugfixed by: Cord
// bugfixed by: Manish
// bugfixed by: Brett Zamir (https://brett-zamir.me)
// note 1: In Locutus, javascript objects are like php associative arrays,
// note 1: thus JavaScript objects will also
// note 1: return true in this function (except for objects which inherit properties,
// note 1: being thus used as objects),
// note 1: unless you do ini_set('locutus.objectsAsArrays', 0),
// note 1: in which case only genuine JavaScript arrays
// note 1: will return true
// example 1: is_array(['Kevin', 'van', 'Zonneveld'])
// returns 1: true
// example 2: is_array('Kevin van Zonneveld')
// returns 2: false
// example 3: is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'})
// returns 3: true
// example 4: ini_set('locutus.objectsAsArrays', 0)
// example 4: is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'})
// returns 4: false
// example 5: is_array(function tmp_a (){ this.name = 'Kevin' })
// returns 5: false

const _getFuncName = function (fn) {
const name = /\W*function\s+([\w$]+)\s*\(/.exec(fn)
if (!name) {
return '(Anonymous)'
}
return name[1]
}
const _isArray = function (mixedVar) {
// return Object.prototype.toString.call(mixedVar) === '[object Array]';
// The above works, but let's do the even more stringent approach:
// (since Object.prototype.toString could be overridden)
// Null, Not an object, no length property so couldn't be an Array (or String)
if (!mixedVar || typeof mixedVar !== 'object' || typeof mixedVar.length !== 'number') {
return false
}
const len = mixedVar.length
mixedVar[mixedVar.length] = 'bogus'
// The only way I can think of to get around this (or where there would be trouble)
// would be to have an object defined
// with a custom "length" getter which changed behavior on each call
// (or a setter to mess up the following below) or a custom
// setter for numeric properties, but even that would need to listen for
// specific indexes; but there should be no false negatives
// and such a false positive would need to rely on later JavaScript
// innovations like __defineSetter__
if (len !== mixedVar.length) {
// We know it's an array since length auto-changed with the addition of a
// numeric property at its length end, so safely get rid of our bogus element
mixedVar.length -= 1
return true
}
// Get rid of the property we added onto a non-array object; only possible
// side-effect is if the user adds back the property later, it will iterate
// this property in the older order placement in IE (an order which should not
// be depended on anyways)
delete mixedVar[mixedVar.length]
return false
}

if (!mixedVar || typeof mixedVar !== 'object') {
return false
}

const isArray = _isArray(mixedVar)

if (isArray) {
return true
}

const iniVal =
(typeof require !== 'undefined' ? require('../info/ini_get')('locutus.objectsAsArrays') : undefined) || 'on'
if (iniVal === 'on') {
const asString = Object.prototype.toString.call(mixedVar)
const asFunc = _getFuncName(mixedVar.constructor)

if (asString === '[object Object]' && asFunc === 'Object') {
// Most likely a literal and intended as assoc. array
return true
}
}

return false
}

A community effort

Not unlike Wikipedia, Locutus is an ongoing community effort. Our philosophy follows The McDonald’s Theory. This means that we assimilate first iterations with imperfections, hoping for others to take issue with-and improve them. This unorthodox approach has worked very well to foster fun and fruitful collaboration, but please be reminded to use our creations at your own risk. THE SOFTWARE IS PROVIDED "AS IS" has never been more true than for Locutus.

Now go and: [ View on GitHub | Edit on GitHub | View Raw ]


« More PHP var functions


Star