Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #28895

Re: how to assure array is of composite objects

From Thomas 'PointedEars' Lahn <PointedEars@web.de>
Newsgroups comp.lang.javascript
Subject Re: how to assure array is of composite objects
Date 2015-11-17 21:17 +0100
Organization PointedEars Software (PES)
Message-ID <23738591.vKiECokzl7@PointedEars.de> (permalink)
References <435aa9ed-7cee-4418-aca3-9e6a2423d7ac@googlegroups.com> <n2cqcp$bal$1@news.albasani.net>

Show all headers | View raw


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] <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays>
[2] <http://www.ecma-international.org/ecma-262/6.0/#sec-float32array>
[3] <https://tc39.github.io/ecma262/#sec-typedarray-objects>

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not cc me. / Bitte keine Kopien per E-Mail.

Back to comp.lang.javascript | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

how to assure array is of composite objects Tod Mar <tamnt54@gmail.com> - 2015-11-16 06:34 -0800
  Re: how to assure array is of composite objects Martin Honnen <mahotrash@yahoo.de> - 2015-11-16 15:49 +0100
    Re: how to assure array is of composite objects Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-11-17 21:17 +0100
  Re: how to assure array is of composite objects "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2015-11-16 20:07 -0800

csiph-web