2012-05-12 35 views
6

Về cơ bản, tôi có một nhà xây dựng như thế này:Đi qua tất cả các đối số cho một constructor

function A() { 
    this.content = toArray(arguments); // toArray converts it to an array 
} 

Tôi muốn gọi nó là từ chức năng khác:

function B() { 
    return new A(); 
} 

Vấn đề là, tôi muốn cũng như chuyển tất cả các đối số được chuyển đến B, tới A.

tôi không thể sử dụng apply (trong một cách phổ biến):

  • Nó sẽ không thể là một nhà xây dựng nếu tôi chỉ apply nó cho bất kỳ đối tượng cũ
  • tôi không thể apply nó vào prototype, trừ khi có một cách dễ dàng để sao chép nó mà tôi không biết về
  • Tôi không thể chỉ cần tạo một new A để chuyển sang lại; trong thực tế, A() ném nếu nó không được chuyển bất kỳ đối số nào và tôi muốn giữ chức năng này.

Tôi đã đưa ra một số giải pháp:

  • constructor khác!

    function C() {} 
    C.prototype = A.prototype; 
    
    function B() { 
        var obj = new C(); 
        A.apply(obj, arguments); 
        return obj; 
    } 
    
  • Một chức năng khác!

    function _A(_arguments) { 
        if(_arguments.length === 0) { 
         return this; 
        } 
    
        // Do initialization here! 
    } 
    
    _A.prototype.constructor = A; 
    
    function A() { 
        if(arguments.length === 0) { 
         throw new Error("That's not good."); 
        } 
    
        return new _A(toArray(arguments)); 
    } 
    
    function B() { 
        return new _A(toArray(arguments)); 
    } 
    
  • Phần còn lại trong số đó là khá nhiều điều tương tự trong một định dạng khác nhau

Nhưng có một cách thực sự dễ dàng và rõ ràng để làm điều này?

Trả lời

7

Trong triển khai ES5, bạn có thể sử dụng Object.create để tạo đối tượng kế thừa từ A.prototype, sau đó .apply() đối tượng kết quả cho hàm tạo.

function A() { 
    this.content = toArray(arguments); // toArray converts it to an array 
} 

function B() { 
    var obj = Object.create(A.prototype); 
    A.apply(obj, arguments); 
    return obj; 
} 

Sau đó, bạn có thể shim Object.create để triển khai không hỗ trợ.

if (!Object.create) 
    Object.create = function(proto) { 
     function f() {} 
     f.prototype = proto; 
     return new f; 
    } 

Tất nhiên, nó không phải là một chút đầy đủ, nhưng nó đủ cho những gì bạn cần.


Hoặc bạn có thể tạo một hàm hoạt động hiệu quả cho tất cả.

function apply_constructor(constr, args) { 
    var obj = Object.create(constr.prototype); 
    constr.apply(obj, args); 
    return obj; 
} 

Và sử dụng nó như thế này:

function B() { 
    return apply_constructor(A, arguments); 
} 
+0

'Object.create' là hoàn hảo. Cảm ơn bạn! – Ryan

+0

@minitech: Bạn được chào đón. –

2

Trong ES5, bạn có thể sử dụng ràng buộc.

function B() { 
    var args = Array.prototype.slice.call(arguments); 
    var curriedCtor = Function.prototype.bind 
     .apply(A, [null].concat(args)); 
    return new curriedCtor(); 
} 

như vậy với

function A(x, y) { 
    this.x = x; 
    this.y = y; 
} 

var test = B(1, 2); 

alert(JSON.stringify(test)); // alerts {"x":1,"y":2} 
Các vấn đề liên quan