认识类数组

「类数组」顾名思义就是类似于数组的东西。比如方法中的arguments就是类数组。

  1. function test() {
  2. console.log(arguments);
  3. // Arguments [callee: ƒ, Symbol(Symbol.iterator): ƒ]
  4. // callee: ƒ test()
  5. // length: 0
  6. // Symbol(Symbol.iterator): ƒ values()
  7. // [[Prototype]]: Object
  8. arguments.push(6); // arguments.push is not a function
  9. }
  10. test(1, 2, 3, 4, 5);

以上代码中arguments是不能使用数组push方法的这是因为「类数组」直接继承于Object.prototype而非Array.prototype
image.png
image.png

对象转类数组

既然「类数组」不是数组那就是个对象喽?我们来模拟一下:

  1. var obj = {
  2. 0: 1,
  3. 1: 2,
  4. 2: 3,
  5. 3: 4,
  6. 4: 5,
  7. length: 5
  8. };
  9. console.log(obj); // {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, length: 5}

但是现在好像还不是,毕竟数组都是[]我们写的这个对象是{}
其实只要对象有**splice**方法并且继承**Array.prototype.splice**方法就会变成类数组!!!

  1. var obj = {
  2. 0: 1,
  3. 1: 2,
  4. 2: 3,
  5. 3: 4,
  6. 4: 5,
  7. length: 5,
  8. splice: Array.prototype.splice
  9. };
  10. console.log(obj); // Object(5) [1, 2, 3, 4, 5, splice: ƒ]
  11. console.log(obj.length); // 5

现在看就是[]的类数组了。
这个时候虽然是数组的形式了,但是依然不能使用push方法,所以我们还可以指定一下push方法:

  1. var obj = {
  2. 0: 1,
  3. 1: 2,
  4. 2: 3,
  5. 3: 4,
  6. 4: 5,
  7. length: 5,
  8. splice: Array.prototype.splice,
  9. push: Array.prototype.push
  10. };
  11. obj.push(10);
  12. console.log(obj); // Object(6) [1, 2, 3, 4, 5, 10, splice: ƒ, push: ƒ]
  13. console.log(obj.length); // 6

我们发现一个问题就是当obj.push(10)obj.length属性也增加了。**push**函数内部的原理其实就是拿到数组的长度作为新下标添加到数组当中,最后**length**属性增加。

  1. Array.prototype.myPush = function (num) {
  2. // 拿到数组的长度最为最新的下标
  3. obj[obj.length] = num;
  4. // 长度增加
  5. this.length++;
  6. };
  7. var obj = {
  8. 0: 1,
  9. 1: 2,
  10. 2: 3,
  11. 3: 4,
  12. 4: 5,
  13. length: 5,
  14. splice: Array.prototype.splice,
  15. push: Array.prototype.myPush
  16. };
  17. obj.push(10);
  18. console.log(obj); // Object(6) [1, 2, 3, 4, 5, 10, splice: ƒ, push: ƒ]
  19. console.log(obj.length); // 6

既然知道了push方法的原理,看到面试题。

  1. var obj = {
  2. 2: 3,
  3. 3: 4,
  4. length: 2,
  5. splice: Array.prototype.splice,
  6. push: Array.prototype.push,
  7. };
  8. obj.push(1);
  9. obj.push(2);
  10. console.log(obj);
  1. var obj = {
  2. 2: 3,
  3. 3: 4,
  4. length: 2,
  5. splice: Array.prototype.splice,
  6. push: Array.prototype.push,
  7. };
  8. // 当 obj 对象继承 Array.prototype.splice 方法后变成类数组
  9. // 调用 push 方法的时候其实是
  10. // obj[2] = 1; 因为初始化长度是 2
  11. // obj[3] = 2; 因为 push(2) 后 length 增加到 3
  12. // 因为改变的是第 2 和第 3 位的元素,所以第 0 位和第 1 位是空,length 为 4
  13. obj.push(1);
  14. obj.push(2);
  15. console.log(obj); // Object(4) [empty × 2, 1, 2, splice: ƒ, push: ƒ]

类数组转数组

利用**Array.prototype.slice**可以把类数组转化为数组!!!

  1. function test(){
  2. var arr = Array.prototype.slice.call(arguments);
  3. console.log(arr); // [1, 2, 3]
  4. }
  5. test(1, 2, 3)