Path: csiph.com!news.mixmin.net!weretis.net!feeder1.news.weretis.net!news.solani.org!.POSTED!not-for-mail From: Thomas 'PointedEars' Lahn Newsgroups: comp.lang.javascript Subject: Re: how to assure array is of composite objects Date: Tue, 17 Nov 2015 21:17:21 +0100 Organization: PointedEars Software (PES) Lines: 189 Message-ID: <23738591.vKiECokzl7@PointedEars.de> References: <435aa9ed-7cee-4418-aca3-9e6a2423d7ac@googlegroups.com> Reply-To: Thomas 'PointedEars' Lahn Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8Bit X-Trace: solani.org 1447791443 18114 eJwFwYEBwDAEBMCVRN9jHBX2HyF39vGwHTTC1jZ9Km0gfRSyRYhrDla6Jq5SvVr/sQjNm3wWZhDe (17 Nov 2015 20:17:23 GMT) X-Complaints-To: abuse@news.solani.org NNTP-Posting-Date: Tue, 17 Nov 2015 20:17:23 +0000 (UTC) User-Agent: KNode/4.14.2 X-User-ID: eJwNyskRACEIBMCU5JgRwnFB8g9h/XY1jMLaTtAxmBTdIjlF7KWSzxsKnU6LeGllX58C6qCt0z2pVPlCj8X9ARPGFAE= Cancel-Lock: sha1:mnfbPpf/YbwQPA0F5ISKm6zWdWo= X-NNTP-Posting-Host: eJwNxYkJADEMA7CVLnHs0HWaZ/8RriAQIVNliAouF4atfcZxsvt1bdLJuEwCJcm6c/xzOH8oFhDQ Xref: csiph.com comp.lang.javascript:28895 Martin Honnen wrote: > Tod Mar wrote: >> What would be the best (most efficient and effective) way to verify that >> an array is of composite objects and not of primitive or some other >> values? I assume it is to write logical code that just does what's >> required. However sometimes in other languages you can make sure the >> 'compile' (or in javascript or lint 'run'), never puts an invalid type >> into a variable. I'm curious if any comments on the preferred solution! > > It seems like a task for the `every` method of arrays, > https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every, > with a suitable check that implements your "requirement of "is of > composite objects and not of primitive or some other values". I am not > too sure what exactly you want to check there, but I guess it goes along > the lines of > > myArray.every(function(item) { return !(typeof item == 'number' || > typeof item == 'boolean' || ...); }) It can be more efficient to use a regular expression here: var rx_excluded_types = /^(?:number|boolean|…)$/; if (myArray.every(function(item) { return !rx_excluded_types.test(typeof item); }) { // … } Also, if one wants to make sure that an array always contains numeric values of a particular kind in the first place, one can use typed arrays: - Float32Array - Float64Array - Int8Array - Int16Array - Int32Array - Uint8Array - Uint8ClampedArray - Uint16ClampedArray - Uint32ClampedArray Those properties of the global object can be called as a constructor and passed a reference to an Array instance. The resulting array-like object has the same indexes but its elements cast to appropriate numeric values (no exception is thrown): /* [1, 0, 5, NaN] */ new Float32Array([1, false, "5", "foo"]) Formerly separately specified [1], some of them are part of the ECMAScript language since the 2015 Edition (6.0). [2] The types of the second group, which are already supported by some implementations, e.g. Google V8 JavaScript, are currently planned to be included in the 2016 Edition (7.0). [3] Where unavailable, it is possible to emulate them using Array.prototype.map() and optionally Proxy¹: if (typeof Int8Array != "function") { var IntArrayConstructorFactory = function (bits) { function _toInt (arg) { /* (ES6, slightly adapted: ) Let n be ToNumber(arg). */ var n = +arg; /* If n is NaN, +0, -0, +∞, or -∞, return +0. */ if (!isFinite(n) || n === 0) { return 0; } /* * Let i be the mathematical value that is the same sign as number * and whose magnitude is floor(abs(number)). */ var i = (n < 0 ? -1 : 1) * Math.floor(Math.abs(n)); /* Let intbit be i modulo 2^bits. */ var power2 = (1 << bits); var intbit = i % power2; /* * If intbit ≥ 2^bits, return intbit - 2^bits; otherwise return * intbit. */ return (intbit >= (1 << (bits - 1))) ? intbit - power2 : intbit; } function _typedArray (a) { var converter = _toInt; a = [].map.call(a, converter); if (typeof Proxy == "function") { var _isIndex = function (name) { name = Math.floor(name); return !Number.isNaN(name) && name > -1 && name < a.length; }; a = new Proxy(a, { "get": function (target, name) { return target[name]; }, "set": function (target, name, value) { var is_index = _isIndex(name); if (!is_index || Number.isNaN(+name)) { target[name] = is_index ? converter(value) : value; } }, "deleteProperty": function (target, name) { if (_isIndex(name)) { target[name] = 0; return true; } return delete target[name]; }, "defineProperty": function (target, name, desc) { if (!_isIndex(name)) { return Object.defineProperty(target, name, desc); } } }); } return a; } return function _IntArray (arg) { if (arguments.length == 0) { if (!(Object(this) instanceof _IntArray)) { /* from Google V8 JavaScript */ throw new TypeError( "Constructor Int" + bits + "Array requires 'new'"); } return _typedArray([]); } if (typeof arg != "object") { var a = []; a.length = +arg; return _typedArray(a); } return _typedArray(arg); }; }; var Int8Array = IntArrayConstructorFactory(8); } ____________ ¹ The obsolete Proxy.create() should not be used instead of “new Proxy()” as specified in ES6 because the proxy object created with the former can work differently. For example, I have observed in Iceweasel/Mozilla JavaScript 38.1.0 (which supports Proxy) that if the proxy created with Proxy.create() does not define a “get” trap, it forwards the property access to the .get() method of the target, if any, instead of simply doing the property read access. If you access the target’s properties in its get() method, this results in infinite recursion and a stack overflow. Also, it should be noted that the “get” trap does not appear to be optional in Iceweasel/Mozilla JavaScript 38.1.0. Accessing the elements of the target works without such a trap, but accessing its “length” property, for example, does not. [1] [2] [3] -- PointedEars FAQ: | SVN: Twitter: @PointedEars2 | ES Matrix: Please do not cc me. / Bitte keine Kopien per E-Mail.