• vue 数组


    今天项目中发现的一个问题:

    在vue项目中输出一个数组,明明有俩个值:0,6,但是length为1

    正常的是这样的

    结果研究发现,是vue源码的问题,具体内容如下:

    转载自:http://www.cnblogs.com/Darlietoothpaste/p/6682407.html

    Vue的数组操作的实现代码大致如下:

     1 const aryMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
     2 const arrayAugmentations = [];
     3 
     4 aryMethods.forEach((method)=> {
     5 
     6     // 这里是原生Array的原型方法
     7     let original = Array.prototype[method];
     8 
     9    // 将push, pop等封装好的方法定义在对象arrayAugmentations的属性上
    10    // 注意:是属性而非原型属性
    11     arrayAugmentations[method] = function () {
    12         console.log('我被改变啦!');
    13 
    14         // 调用对应的原生方法并返回结果
    15         return original.apply(this, arguments);
    16     };
    17 
    18 });
    19 
    20 let list = ['a', 'b', 'c'];
    21 // 将我们要监听的数组的原型指针指向上面定义的空数组对象
    22 // 别忘了这个空数组的属性上定义了我们封装好的push等方法
    23 list.__proto__ = arrayAugmentations;
    24 list.push('d');  // 我被改变啦! 4
    25 
    26 // 这里的list2没有被重新定义原型指针,所以就正常输出
    27 let list2 = ['a', 'b', 'c'];
    28 list2.push('d');  // 4

    在Vue的官方文档中,有着如下的提示:

    1. 当你利用索引直接设置一个项时,例如: vm.items[indexOfItem] = newValue
    2. 当你修改数组的长度时,例如: vm.items.length = newLength

    这个是Js语法的限制,什么限制呢?

    先来看一下,在这篇文章中写到,为什么不利用如下的代码来实现:

     1 function FakeArray() {
     2   return  Array.call(this,arguments);
     3 }
     4 
     5 FakeArray.prototype = [];
     6 FakeArray.prototype.constructor = FakeArray;
     7 
     8 FakeArray.prototype.push = function () {
     9     console.log('我被改变啦');
    10     return Array.prototype.push.call(this,arguments);
    11 };
    12 
    13 let list = ['a','b','c'];
    14 
    15 let fakeList = new FakeArray(list);

    然而,作者在测试代码的时候,发现fakeList实际上是一个数组,而且它的push是内置的push方法,并不是继承FakeArray的方法。

    在作者文章的评论中,有个网友评论说,这是因为Array.call并不会引用this,不止Array,String,Number,Regexp,Object等等JS的内置类都不行。

    所以实际上代码是这样的:

    function FakeArray() {
      return  Array(arguments);
    }

    这也就是ES5以下无法完美继承数组的问题,回过头看一下Vue中的实现,Vue的作者用的是__proto__属性,该属性指向构造对象的原型。

    也就是说,上面的例子我们可以这样改写:

     1 function FakeArray() {
     2   var x =  Array.call(null,arguments);
     3    x.__proto__ = FakeArray.prototype
     4    return x;
     5 }
     6 
     7 FakeArray.prototype = [];
     8 FakeArray.prototype.constructor = FakeArray;
     9 
    10 FakeArray.prototype.push = function () {
    11     console.log('我被改变啦');
    12     return Array.prototype.push.call(this,arguments);
    13 };
    14 
    15 let list = ['a','b','c'];
    16 
    17 let fakeList = new FakeArray(list);

    但是呢,这样写,也就意味着我们不能检测到length,和fakeList[x] = 1;这样的操作,也就有了Vue文档中的提示了。

    本文参考自https://github.com/youngwind/blog/issues/85及其评论。

  • 相关阅读:
    教你轻松搞定javascript中的正则
    带你学习javascript的函数进阶(二)
    带你学习Javascript中的函数进阶(一)
    带你学习ES5中新增的方法
    作为前端,你需要懂得javascript实现继承的方法
    作为前端,你需要了解的js构造函数和原型
    ES6学习笔记(三):教你用js面向对象思维来实现 tab栏增删改查功能
    企业级zabbix监控搭建及邮件报警
    -bash: netstat: 未找到命令
    shell点名脚本不重复人名
  • 原文地址:https://www.cnblogs.com/zhaobao1830/p/7143839.html
Copyright © 2020-2023  润新知