關於Vue數組操做

 

Vue的數組操做的實現代碼大體以下:git

const aryMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
const arrayAugmentations = [];

aryMethods.forEach((method)=> {

    // 這裏是原生Array的原型方法
    let original = Array.prototype[method];

   // 將push, pop等封裝好的方法定義在對象arrayAugmentations的屬性上
   // 注意:是屬性而非原型屬性
    arrayAugmentations[method] = function () {
        console.log('我被改變啦!');

        // 調用對應的原生方法並返回結果
        return original.apply(this, arguments);
    };

});

let list = ['a', 'b', 'c'];
// 將咱們要監聽的數組的原型指針指向上面定義的空數組對象
// 別忘了這個空數組的屬性上定義了咱們封裝好的push等方法
list.__proto__ = arrayAugmentations;
list.push('d');  // 我被改變啦! 4

// 這裏的list2沒有被從新定義原型指針,因此就正常輸出
let list2 = ['a', 'b', 'c'];
list2.push('d');  // 4

在Vue的官方文檔中,有着以下的提示:github

  1. 當你利用索引直接設置一個項時,例如: vm.items[indexOfItem] = newValue
  2. 當你修改數組的長度時,例如: vm.items.length = newLength

這個是Js語法的限制,什麼限制呢?數組

先來看一下,在這篇文章中寫到,爲何不利用以下的代碼來實現:app

function FakeArray() {
  return  Array.call(this,arguments);
}

FakeArray.prototype = [];
FakeArray.prototype.constructor = FakeArray;

FakeArray.prototype.push = function () {
    console.log('我被改變啦');
    return Array.prototype.push.call(this,arguments);
};

let list = ['a','b','c'];

let fakeList = new FakeArray(list);

然而,做者在測試代碼的時候,發現fakeList其實是一個數組,並且它的push是內置的push方法,並非繼承FakeArray的方法。測試

在做者文章的評論中,有個網友評論說,這是由於Array.call並不會引用this,不止Array,String,Number,Regexp,Object等等JS的內置類都不行。this

因此實際上代碼是這樣的:spa

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

 

這也就是ES5如下沒法完美繼承數組的問題,回過頭看一下Vue中的實現,Vue的做者用的是__proto__屬性,該屬性指向構造對象的原型。prototype

也就是說,上面的例子咱們能夠這樣改寫:指針

 

function FakeArray() {
  var x =  Array.call(null,arguments);
   x.__proto__ = FakeArray.prototype
   return x;
}

FakeArray.prototype = [];
FakeArray.prototype.constructor = FakeArray;

FakeArray.prototype.push = function () {
    console.log('我被改變啦');
    return Array.prototype.push.call(this,arguments);
};

let list = ['a','b','c'];

let fakeList = new FakeArray(list);

 

可是呢,這樣寫,也就意味着咱們不能檢測到length,和fakeList[x] = 1;這樣的操做,也就有了Vue文檔中的提示了。code

本文參考自https://github.com/youngwind/blog/issues/85及其評論。

相關文章
相關標籤/搜索