2011-12-16 25 views
8

Tôi đã cố gắng làm cho mã của mình nhỏ hơn bằng cách lưu vào bộ nhớ các hàm. Ví dụ:"đối tượng không phải là một hàm" khi lưu hàm.call thành một biến

function test(){ 
    var a = Array.prototype.slice, 
    b = a.call(arguments); 
    // Do something 
    setTimeout(function(){ 
    var c = a.call(arguments); 
    // Do something else 
    }, 200); 
} 

Vì vậy, thay vì gọi Array.prototype.slice.call(arguments), tôi chỉ có thể làm a.call(arguments);.

Tôi đã cố gắng làm cho điều này thậm chí nhỏ hơn bằng cách lưu vào bộ nhớ cache Array.prototype.slice.call, nhưng điều đó không hoạt động.

function test(){ 
    var a = Array.prototype.slice.call, 
    b = a(arguments); 
    // Do something 
    setTimeout(function(){ 
    var c = a(arguments); 
    // Do something else 
    }, 200); 
} 

Điều này cho tôi TypeError: object is not a function. Tại sao vậy?

typeof Array.prototype.slice.call trả về "function", như mong đợi.

Tại sao tôi không thể lưu .call vào một biến (và sau đó gọi nó)?

+0

công cụ javascript nào đã cho bạn lỗi này? –

+0

có thể trùng lặp của [Làm thế nào để bạn tham khảo Array.prototype.slice.call()?] (Http://stackoverflow.com/questions/6835315/how-do-you-reference-array-prototype-slice-call) – pimvdb

+0

@DanD .: Chrome 16. –

Trả lời

7

Function.prototype.call là một chức năng bình thường hoạt động trên các chức năng thông qua như this.

Khi bạn gọi call từ một biến, this trở thành window, không phải là chức năng.
Bạn cần phải viết call.call(slice, someArray, arg1, arg2)

+0

Gọn gàng, nó hoạt động. 'var a = Array.prototype.slice, b = a.call; b.call (a, đối số) '. Vì vậy, có cách nào để "ràng buộc" 'này' khi sao chép' .call'? –

+2

@Rocket: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind – SLaks

+0

Vì vậy, 'var a = Array.prototype.slice.call.bind (Array.prototype.slice)'?Chỉnh sửa: Wow, mà thực sự hoạt động! Chỉnh sửa 2: Theo trang 'var slice = Function.prototype.call.bind (Array.prototype.slice);' cũng hoạt động! Khéo léo! –

5

Hãy thử điều này:

function test(){ 
    var a = function(args){ 
     return Array.prototype.slice.call(args); 
    }; 
    b = a(arguments); 
    // Do something 
    setTimeout(function(){ 
    var c = a(arguments); 
    // Do something else 
    }, 200); 
} 

Các lỗi tương tự sẽ xảy ra nếu bạn cố gắng làm một cái gì đó như:

var log = console.log; 
log("Hello"); 

Lý do là khi bạn làm điều này bạn đang gán chức năng x (trong tôi ví dụ log) đến biến số log. NHƯNG chức năng chứa gọi this mà hiện nay đề cập đến window và không console, sau đó ném một lỗi mà this is not an object

+0

Lạ, 'var log = console.log; log ('a'); 'cho' TypeError: lời gọi bất hợp pháp' trong Chrome 16, nhưng 'var logX = console.log.bind (console); logX ('a'); 'works :-P –

4

Vấn đề là call là một phương pháp (một chức năng mà thuộc về một đối tượng) mà hy vọng chủ nhân của nó (this của nó) là một hàm. Khi bạn viết a = Array.prototype.slice.call, bạn đang sao chép hàm chứ không phải chủ sở hữu.

Thông báo "đối tượng không phải là chức năng" không nói rằng a không phải là chức năng, nó nói rằng this của nó không phải là một chức năng. Bạn về mặt kỹ thuật có thể đạt được những gì bạn mô tả bằng cách viết a.call(Array.prototype.slice, arguments), nhưng rõ ràng đó không phải là những gì bạn muốn!

+0

Cool, 'a.call (Array.prototype.slice, arguments)' thực sự hoạt động. Tôi thấy rằng khi bạn sao chép một hàm, 'this' sẽ được tham chiếu chính xác. –

+2

@Rocket: Không - không thể - bởi vì chúng tôi cần có khả năng thực hiện điều gì đó như 'a.foo = b.foo' hoặc' A.prototype.foo = B.prototype.foo' hoặc không muốn sao chép một phương thức từ đối tượng này sang đối tượng khác. Sẽ rất khó hiểu nếu một cuộc gọi đến 'a.foo()' hoạt động trên 'b' thay vì' a'! – ruakh

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