Guest User

Untitled

a guest
Sep 12th, 2018
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.58 KB | None | 0 0
  1. // 12 September 2018
  2. // possible blog post
  3.  
  4. // Array.from() and Array.prototype.slice.call() can take objects with
  5. // coercibly numeric keys and a length property to produce a new array.
  6.  
  7. // if length is inaccurate (2 instead of 1, e.g.), you get empty slots
  8. console.log(Array.from({ 0: 'first', length: 2 })); // Array [ "first", undefined ]
  9. console.log([].slice.call({ 0: 'first', length: 2 })); // Array [ "first", <1 empty slot> ]
  10.  
  11. // if length is accurate but an index is missing, you get empty slots
  12. console.log(Array.from({ 0: 'first', '': 'next', 2: 'last', length: 3 })); // Array [ "first", undefined, "last" ]
  13. console.log([].slice.call({ 0: 'first', '': 'next', 2: 'last', length: 3 })); // Array [ "first", <1 empty slot>, "last" ]
  14.  
  15. // if length is floating point, you get the integer value
  16. console.log(Array.from({ 0: 'first', length: 1.9999999999999 })); // Array [ "first" ]
  17. console.log([].slice.call({ 0: 'first', length: 1.999999999999 })); // Array [ "first" ]
  18.  
  19. // if length is boolean, you get 1 or 0
  20. console.log(Array.from({ 0: 'first', 1: 'next', length: false })); // Array []
  21. console.log([].slice.call({ 0: 'first', length: false })); // Array []
  22.  
  23. console.log(Array.from({ 0: 'first', '1': 'next', length: true })); // Array [ "first" ]
  24. console.log([].slice.call({ 0: 'first', 1: 'next', length: true })); // Array [ "first" ]
  25.  
  26. // if length is missing or not coercibly numeric, you get nothing
  27. console.log(Array.from({ 0: 'first' })); // Array []
  28. console.log([].slice.call({ 0: 'first' })); // Array []
  29.  
  30. // if length is an array that toString() turns into a coercible number, that's what you get
  31. console.log(Array.from({ 0: 'ok', length: ['1'] })); // Array [ "ok" ]
  32. console.log([].slice.call({ 0: 'wow', length: ['2']})); // Array [ "wow", <1 empty slot> ]
  33.  
  34. // if the object has both numeric and string versions of a key, you'll get the last-defined entry
  35. console.warn(Array.from({ 0: 'first', length: 1, '0': 'more' })); // Array [ "more" ]
  36. console.warn(Array.from({ '0': 'first', length: 1, 0: 'more' })); // Array [ "more" ]
  37.  
  38. // if a key is a floating point, it is ignored
  39. console.warn(Array.from({ length: 1, '1.1': 'more' })); // Array [ undefined ]
  40.  
  41. // Now that we know all that, we can look at the standard usages and derive a
  42. // convertible length-less object with numeric keys and run that through from and slice
  43.  
  44. var test = Array.from({ 0: 'first', length: 1 });
  45. console.log(test); // Array [ "first" ]
  46.  
  47. var test2 = [].slice.call({ 0: 'first', 2: 'last', length: 3 });
  48. console.log(test2); // Array(3) [ "first", <1 empty slot>, "last" ]
  49.  
  50. var test3 = Array.from({ 0: 'first', '1': 'next', length: 2 });
  51. console.log(test3); // Array [ "first", "next" ]
  52.  
  53. // Now let's make an array out of an object without a length property
  54. var source = { 0: 'first', '1': 'next', 2: 'last', NaN: 'not a number', null: 'null', undefined: void 0, '-1': 'negative 1', '1.1': '1.1', '2.0': 'dupe' };
  55.  
  56. // get all 0-based integer keys
  57. var keys = Object.keys(source).filter((key) => {
  58. var v = Number.parseInt(''+key, 10);
  59. // not NaN, integer, 0-based
  60. return v === v && ''+ Number.parseInt(key) === key && v >= 0;
  61. });
  62.  
  63. console.info('our keys');
  64. console.log(keys);
  65.  
  66. // walk the keys and insert matching source key entries onto the target
  67. var length = keys.length;
  68. var target = keys.reduce((target, key) => {
  69. target[key] = source[key];
  70. return target;
  71. }, { length });
  72.  
  73. console.info('our target');
  74. console.log(target);
  75.  
  76. // test it out
  77.  
  78. console.log('our tests');
  79.  
  80. var test4 = Array.from(target);
  81. console.log(test4); // Array(3) [ "first", "next", "last" ]
  82.  
  83. var test5 = [].slice.call(target);
  84. console.log(test5); // Array(3) [ "first", "next", "last" ]
Add Comment
Please, Sign In to add comment