2009-02-21 37 views
24

Tôi đang cố gắng mở rộng phương thức Array.push để sử dụng push sẽ kích hoạt phương thức gọi lại, sau đó thực hiện chức năng mảng bình thường.Làm cách nào để mở rộng Array.prototype.push()?

Tôi không chắc chắn cách thực hiện việc này, nhưng đây là một số mã tôi đã chơi không thành công.

arr = []; 
arr.push = function(data){ 

    //callback method goes here 

    this = Array.push(data); 
    return this.length; 

} 

arr.push('test'); 

Trả lời

62

Vì đẩy cho phép nhiều hơn một phần tử được đẩy, tôi sử dụng biến đối số bên dưới để cho phép phương thức đẩy thực có tất cả các đối số.

Giải pháp này chỉ ảnh hưởng đến biến arr:

arr.push = function(){ 
    //Do what you want here... 
    return Array.prototype.push.apply(this,arguments); 
} 

giải pháp này ảnh hưởng đến tất cả các mảng. Tôi không khuyên bạn làm điều đó.

Array.prototype.push=(function(){ 
    var original = Array.prototype.push; 
    return function() { 
     //Do what you want here. 
     return original.apply(this,arguments); 
    }; 
})(); 
+0

Hình thức gói chức năng yêu thích của tôi là vượt qua Array.prototype.push khi bạn thực hiện hàm bên ngoài của mình và chấp nhận nó trong hàm làm biến ban đầu. Đó là một chút ngắn gọn hơn – pottedmeat

+9

@pottedmeat: nhưng nó ít có thể đọc được - hãy nhớ rằng, các chương trình không chỉ được viết cho máy, mà còn cho các lập trình viên khác nữa! – Christoph

+1

@some Cảm ơn bạn rất nhiều vì đã giải thích rõ nguyên mẫu và không! – Dorjan

4

Bạn có thể làm theo cách này:

arr = [] 
arr.push = function(data) { 
    alert(data); //callback 

    return Array.prototype.push.call(this, data); 
} 

Nếu bạn đang ở trong một tình huống mà không cần gọi, bạn cũng có thể đi cho giải pháp này:

arr.push = function(data) { 
    alert(data); //callback 

    //While unlikely, someone may be using psh to store something important 
    //So we save it. 
    var saved = this.psh; 
    this.psh = Array.prototype.push; 
    var ret = this.psh(data); 
    this.psh = saved; 
    return ret; 
} 

Edit:

Trong khi tôi đang nói cho bạn cách làm điều đó, bạn có thể được phục vụ tốt hơn bằng cách sử dụng một phương pháp khác thực hiện gọi lại sau đó chỉ cần gọi pu sh trên mảng chứ không phải là ghi đè. Bạn có thể kết thúc với một số tác dụng phụ không mong muốn. Ví dụ, push dường như là varadic (có một số biến đối số, như printf), và sử dụng ở trên sẽ phá vỡ điều đó.

Bạn sẽ cần phải làm lộn xộn với _Arguments() và _ArgumentsLength() để ghi đè chính xác chức năng này. Tôi rất khuyên bạn nên chống lại con đường này.

Chỉnh sửa một lần nữa: Hoặc bạn có thể sử dụng "đối số", điều đó cũng sẽ hoạt động. Tuy nhiên, vẫn khuyên bạn nên tham gia tuyến đường này.

+0

Array.prototype.push.call (điều này, dữ liệu); wont làm việc như Array có thể mất nhiều mục. Array.prototype.push.apply (điều này, đối số); – ToughPal

-1

tôi sẽ làm điều này:

var callback = function() { alert("called"); }; 
var original = Array.prototype.push; 
Array.prototype.push = function() 
{ 
    callback(); 
    return original.apply(this, arguments); 
}; 

Nếu bạn muốn một cuộc tranh cãi là một callback, bạn có thể làm điều này:

var original = Array.prototype.push; 
Array.prototype.push = function(callback) 
{ 
    callback(); 
    return original.apply(this, Array.prototype.slice.call(arguments, 1)); 
} 

Những cả đã được thử nghiệm.

+1

@cdmckay: Nếu bạn đã thử nghiệm nó, bạn sẽ nhận thấy rằng bạn đã tạo ra một vòng lặp vô hạn ... – some

+0

@some xấu của tôi, tôi đã viết rằng cuối đêm qua. Tôi đã cố định và thử nghiệm chúng. – cdmckay

+1

@cdmckay: Bây giờ nó hoạt động, nhưng bạn gây ô nhiễm không gian tên toàn cầu với 'nguyên bản', và nếu một số chức năng khác thay đổi giá trị của 'ban đầu' bạn đã phá vỡ việc đẩy mảng. Giải pháp thứ hai của bạn không có ý nghĩa: Nếu tôi phải cung cấp gọi lại khi tôi đẩy, tôi có thể gọi lại cuộc gọi lại. – some

4

Array.prototype.push được giới thiệu trong JavaScript 1.2. Nó thực sự đơn giản như thế này:

Array.prototype.push = function() { 
    for(var i = 0, l = arguments.length; i < l; i++) this[this.length] = arguments[i]; 
    return this.length; 
}; 

Bạn luôn có thể thêm một cái gì đó ở phía trước đó.

0

Tôi muốn gọi một hàm sau đối tượng đã được đẩy lên mảng, vì vậy tôi đã điều sau đây:

myArray.push = function() { 
    Array.prototype.push.apply(this, arguments); 
    myFunction(); 
    return myArray.length; 
}; 

function myFunction() { 
    for (var i = 0; i < myArray.length; i++) { 
     //doSomething; 
    } 
} 
1

Trước tiên, bạn cần phân lớp Array:

ES6: (không tương thích với babel hoặc trình duyệt khác ngoài Chrome50 + ngay bây giờ https://kangax.github.io/compat-table/es6/)

class SortedArray extends Array { 
    constructor(...args) { 
     super(...args); 
    } 
    push() { 
     return super.push(arguments); 
    } 
} 

es5 :(proto gần như bị phản đối nhưng nó là giải pháp duy nhất cho bây giờ)

function SortedArray() { 
    var arr = []; 
    arr.push.apply(arr, arguments); 
    arr.__proto__ = SortedArray.prototype; 
    return arr; 
} 
SortedArray.prototype = Object.create(Array.prototype); 

SortedArray.prototype.push = function() { 
    this.arr.push(arguments); 
}; 
+0

Tò mò tại sao bạn thêm câu trả lời cho câu hỏi từ 7 tuổi trở lên. – Geuis

+1

Tò mò tại sao một người nào đó sẽ không? JS đã thay đổi. – pat

Các vấn đề liên quan