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及其評論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM