2016-03-15 13 views
0

我創建了像原型的數組:原型失去了對片上陣列狀的結構

function METracker() {} 
METracker.prototype = Object.create(Array.prototype); 
METracker.prototype.myMethod = function(aStd) { 
    return true; 
}; 

現在我創建一個實例:

var aInst = new METracker('a', 'b', 'c'); 

現在,我要克隆它,所以我做的:

var cloneInst = aInst.slice(); 

然而cloneInst不再在方法.myMethod有沒有辦法來保持原鍵入克隆?

感謝

+3

這是因爲'slice'返回'Array'對象,而不是'METracker'對象,'Array'對象沒有'myMethod'。 – thefourtheye

+0

謝謝,我試圖讓分片返回'METracker'這可能嗎? – Noitidart

+1

不幸的是,除非你可以自己改變'slice'函數。否則,你需要在'METracker'上構建你自己的'slice'包裝器,它將切片並返回一個'METracker'實例。 – thefourtheye

回答

1

如果你要創建自己的數組一樣,關鍵是要擴大一個數組實例,而不是數組原型:

function MyAry() { 
 
    var self = []; 
 

 
    [].push.apply(self, arguments); 
 

 
    // some dark magic 
 

 
    var wrap = 'concat,fill,filter,map,slice'; 
 
    wrap.split(',').forEach(function(m) { 
 
     var p = self[m]; 
 
     self[m] = function() { 
 
      return MyAry.apply(null, p.apply(self, arguments)); 
 
     } 
 
    }); 
 

 
    // add your stuff here 
 

 
    self.myMethod = function() { 
 
     document.write('values=' + this.join() + '<br>'); 
 
    }; 
 

 
    return self; 
 
} 
 

 

 
a = new MyAry(11,44,33,22); 
 
a.push(55); 
 
a[10] = 99; 
 
a.myMethod() 
 

 
b = a.sort().slice(0, 4).reverse(); 
 
b.myMethod();

基本上,你創建一個新的數組(一個正常的數組,不是你的對象),包裝一些數組方法,以便它們返回對象而不是通用數組,並將自定義方法添加到該實例。所有其他數組方法和索引操作繼續處理您的對象,因爲它只是一個數組。

+0

非常感謝georg這個作品絕對精湛! – Noitidart

1

我創建了像原型的數組:

不,你沒有。 (){}

function METracker(){} METracker.prototype = Object.create(Array.prototype); METRAcker.prototype.myMethod = function(aStd){ return true; };

METracker構造函數什麼都不做的話,那將只是返回其[[Prototype]]鏈Array.prototype的新對象。

var aInst = new METracker('a','b','c');

只是返回一個METracker的實例,它沒有數據,因爲構造函數沒有對傳遞的參數做任何事情。將Array.prototype分配給繼承鏈並不意味着調用Array構造函數。

var cloneInst = aInst.slice();

注意callling 片()aInst只返回一個新的空數組。 aInst沒有長度屬性,所以切片的算法沒有任何值得重複。即使aInst具有屬性,切片只會遍歷整數值從0到aInst.length - 1存在的數字切片。

如果你想創建一個用於創建陣列狀物體構造函數,考慮是這樣的:

function ArrayLike() { 
 
    // Emulate Array constructor 
 
    this.length = arguments.length; 
 
    Array.prototype.forEach.call(arguments, function(arg, i) { 
 
    this[i] = arg; 
 
    }, this); 
 
} 
 

 
ArrayLike.prototype = Object.create(Array.prototype); 
 

 
var a = new ArrayLike(1,2,3); 
 
document.write(a.length); 
 
document.write('<br>' + a.join());

上述只是打碼,還有很多事情要做。修復長度問題並不容易,我不確定它可以做到。也許需要有一個私有的「fixLength」方法,但是像splice這樣的方法需要調整長度並在發生變化時修復索引,因此您必須編寫一個模擬Array構造函數的構造函數和許多方法來執行re - 適當調整長度(推動,彈出,移動,不移動等)。

+0

非常感謝Rob我真的從這裏學到了一噸! – Noitidart