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

在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'); //

在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的内置类都不行。

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

  1. function FakeArray() {
  2. return Array(arguments);
  3. }

这也就是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及其评论。

vue 数组的更多相关文章

  1. [one day one question] Vue数组变更不能触发刷新

    问题描述:Vue数组变更不能触发刷新,特别是数组的每个元素都是对象的时候,对象中某个属性的值发生变化,根本无法触发Vue的dom刷新,这怎么破? 解决方案:this.$set(array, index ...

  2. vue 数组渲染问题

    vue 数组渲染问题 问题一: 用v-for循环渲染数组数据时,数据更新了,视图却没有更新 由于 JavaScript 的限制, Vue 不能检测以下变动的数组: 1. 当你利用索引直接设置一个项时, ...

  3. vue数组变异方法

    Vue数组变异方法,会改变被这些方法调用的原始数组,将会触发视图更新 push() 接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度 pop() 从数组末尾移除最后一项,减少数组的 ...

  4. Vue数组更新及过滤排序

    前面的话 Vue为了增加列表渲染的功能,增加了一组观察数组的方法,而且可以显示一个数组的过滤或排序的副本.本文将详细介绍Vue数组更新及过滤排序 变异方法 Vue 包含一组观察数组的变异方法,它们将会 ...

  5. vue 数组 新增元素 响应式原理 7种方法

    1.问题 思考一个问题,以下代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  6. vue 数组更新 this.$set(this.dataList, data.index, data.data)

    vue 数组更新 this.$set(this.dataList, data.index, data.data) https://www.cnblogs.com/huangenai/p/9836811 ...

  7. vue 数组和对象渲染问题

    vue 数组和对象渲染问题 最近项目有点忙碌,遇到好多问题都没有总结(╥﹏╥),在开发过程中,取vuex中的数组渲染完成之后,再次修改数组的值,数据更新了,但是视图并没有更新.以为是数组更新的问题,后 ...

  8. vue 数组对接字符串 传值时候,join(',') 一下 watch

    vue 数组对接字符串 传值时候,join(',') 一下 watch watch: { 'tFill.otherDescArr': function (newVal, oldVal) { this. ...

  9. vue数组更新界面无变化

    1. vue数组更新界面无变化 1.1. 说明 对数组进行更新或者添加,一定要注意方式,我的情况是数组套数组,双重循环,在造数据的时候,不断从尾部添加数据,所以写成了如下形式,每次下拉都会去加载一批相 ...

  10. WTF!! Vue数组splice方法无法正常工作

    当函数执行到this.agents.splice()时,我设置了断点.发现传参index是0,但是页面上的列表项对应的第一行数据没有被删除, WTF!!! 这是什么鬼!然后我打开Vue Devtool ...

随机推荐

  1. Oracle DROPtable以及Truncate table 的简单测试

    1. 一个用户库 有一个业务表比较大 大小是 49g 表的行数为:121546147 一亿两千万行 制作一个虚拟机的快照测试一下 drop table 和 truncate table的性能差距 2. ...

  2. Java线程池停止空闲线程是否有规则呢?

    Java线程池中线程的数量超过核心线程的数量,且所有线程空闲,空闲时间超过keepAliveTime,会停止超过核心线程数量的线程,那么会保留哪些线程呢?是不是有规则呢? 测试代码: ThreadPo ...

  3. Tether USDT 节点钱包的安装与使用-omni layer

    1 什么是Omni Layer Omni Layer是一种通信协议,它使用比特币区块链实现智能合约,用户货币和分散式点对点交换等功能. Omni Core是基于比特币核心代码库的快速,便携式Omni层 ...

  4. P3254 圆桌问题

    题目链接 非常简单的一道网络流题 我们发现每个单位的人要坐到不同餐桌上,那也就是说每张餐桌上不能有同一单位的人.这样的话,我们对于每个单位向每张餐桌连一条边权为1的边,表示同一餐桌不得有相同单位的人. ...

  5. SQL问题(面试题)

    面试完后在本地mysql数据库中重现了该问题 数据表stuscore信息如下: 1.计算每个人的总成绩,并且排名(要求显示字段 学号 姓名 总成绩)SELECT stuid AS 学号,NAME AS ...

  6. MT【77】函数的定义理解

    答案:D.比如C 中令$x^2+1=2,x=-1,1,$ 得$f(2)=0,2$与定义矛盾,A,B同理排除. D中注意到$x^2-2x$与$|x-1|$对称轴都是$x=1$. 评:函数的定义,首先是两 ...

  7. BZOJ 4540 [Hnoi2016]序列 | 莫队 详细题解

    传送门 BZOJ 4540 题解 --怎么说呢--本来想写线段树+矩阵乘法的-- --但是嘛--yali的机房太热了--困--写不出来-- 于是弃疗,写起了莫队.(但是我连莫队都想不出来!) 首先用单 ...

  8. raft 论文

    raft 论文,摘自  http://www.infoq.com/cn/articles/raft-paper raft动画:https://raft.github.io/ raft说明动画:

  9. IOI2018题解

    只有部分题解 练习赛 T2 自然还是要简单考虑了 0~n-1的排列,考虑相对的大小 我们先考虑对于前三个:a,b,c 询问a,b,询问b,c,再询问a,b,c 发现,如果三个知道两个,那么第三个可以唯 ...

  10. python之旅:网络编程

    一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务端为你提供视频 ...