Hacker News new | ask | show | jobs
by irjustin 1992 days ago
#3 is interesting because you can assign arr[-1] and it's valid. But it goes from being a pure array to a mixed array+hash/dict where "-1" is the key.

BUT if you set/access arr[0] it's just like an array...

  arr = []
  arr[-1] = 'neg-one-pos'
  arr[0] = 'zero-pos'
  arr[1] = 'one-pos'
  
  arr # => ["zero-pos", "one-pos", -1: "neg-one-pos"]
That was quite unexpected for me.
1 comments

Wow, this truly is an "array with a hash/dict at the end"

  arr = []
  arr[-1] = 'neg-one-key'
  arr[0] = 'zero-pos'
  arr[1] = 'one-pos'
  arr[2] = 'two-pos'
  arr[-2] = 'neg-two-key'
  arr[3] = 'three-pos'
  
  arr // => ["zero-pos", "one-pos", "two-pos", "three-pos", -1: "neg-one-key", -2: "neg-two-key"]

  arr.splice(2, 1)

  arr // => ["zero-pos", "one-pos", "three-pos", -1: "neg-one-key", -2: "neg-two-key"]

  arr[3] // => undefined
Incredibly weird for me.
That’s because arrays are also objects in JS, and objects can have new properties added, which are implemented as hash strings. Everything in JS is a kind of object, including functions.
Not quite everything. JavaScript does have some primitives, though it also provides object wrappers for those primitives via the new operator.

  > let numberPrimitive = 0;
  undefined
  > let numberObject = new Number(0);
  undefined
  > typeof(numberPrimitive);
  'number'
  > typeof(numberObject);
  'object'
  > typeof(numberObject + numberObject);
  'number'
  > numberPrimitive;
  0
  > numberObject;
  [Number: 0]
  > numberPrimitive.one = 1;
  1
  > numberObject.one = 1;
  1
  > numberPrimitive.one;
  undefined
  > numberObject.one;
  1
  > numberPrimitive;
  0
  > numberObject;
  [Number: 0] { one: 1 }
Just using parenthesis is enough for wrapping:

    > 0.toString()
    Thrown:
    0.toString()
    ^^
    
    SyntaxError: Invalid or unexpected token
    > (0).toString()
    '0'
Parens aren't doing the same thing. Primitives are implicitly being wrapped in objects when you use methods, but they come out on the other end as primitives again. The new operator gives you an object wrapper that you can keep working with and modifying the values of, whereas the parens you're using just let the interpreter know that your period isn't a decimal point. You can also use a space for this.

  > typeof(new Number(0));
  'object'
  > typeof((0));
  'number'
  > 0 .toString();
  '0'