2011-11-11 11 views
5
function asArray(quasiArray, start) { 
    var result = []; 
    for (var i = (start || 0); i < quasiArray.length; i++) 
    result.push(quasiArray[i]); 
    return result; 
} 

function partial(func) { 
    var fixedArgs = asArray(arguments, 1); 
    return function(){ 
    return func.apply(null, fixedArgs.concat(asArray(arguments))); 
    }; 
} 

function compose(func1, func2) { 
    return function() { 
    return func1(func2.apply(null, arguments)); 
    }; 
} 

var isUndefined = partial(op["==="], undefined); 
var isDefined = compose(op["!"], isUndefined); 
show(isDefined(Math.PI)); 
show(isDefined(Math.PIE)); 

Tại sao có thể không phải là chức năng soạn chỉ cần trả:Tôi đang đọc Eloquent Javascript và tôi hơi bối rối bởi ví dụ chức năng một phần này. Xin vui lòng giúp giải thích

func1(func2); 

và cung cấp cho các đầu ra thích hợp. Tôi nghĩ rằng một phần chức năng được lưu trữ trong biến isUndefined đã trả về func.apply (null, [cố định, đối số])

var op = { 
"+": function(a, b){return a + b;}, 
"==": function(a, b){return a == b;}, 
"===": function(a, b){return a === b;}, 
"!": function(a){return !a;} 
/* and so on */ 
}; 
+0

'op' được khai báo ở đâu? Bạn có thể thêm nó vào? –

+0

Rất tiếc, xin lỗi – Shaan

Trả lời

2

Cả hai partialcomposehigher-order functions.

isUndefined sẽ trả về một hàm, khi được gọi, sẽ gọi hàm ban đầu được truyền với các đối số gốc cộng với bất kỳ đối số mới nào được truyền tại lời gọi.

Để trả lời câu hỏi của bạn, bạn sẽ gọi số apply trên hàm được trả lại từ partial mà lần lượt, gọi apply trên chức năng ban đầu được chuyển đến partial.

Bạn muốn compose trả về một hàm khi được gọi, sẽ trả về kết quả của việc gọi hàm đầu tiên đã chuyển hàm thứ hai làm đối số (với hàm thứ hai đã truyền các đối số được chuyển đến lời gọi compose). Nếu compose trả về func1(func2), thì bạn sẽ chỉ định kết quả của lời gọi đến biến số isDefined.

EDIT:

Bây giờ chúng ta có op, chúng ta hãy cố gắng phân hủy này:

var isUndefined = partial(op["==="], undefined); 

này tương đương với

var isUndefined = partial(function(a, b){return a === b;}, undefined); 

isUndefined được gán một chức năng đó, khi được gọi, sẽ gọi hàm được chuyển làm đối số đầu tiên cho partial, chuyển i n undefined như là đối số đầu tiên mà gọi hàm, tiếp theo là các đối số truyền cho hàm isUndefined ví dụ:

partial(function(a, b){return a === b;}, undefined /* this will become 'a' when isUndefined is invoked */)(argumentForisUndefined /* this will become 'b' when isUndefined is invoked */); 

isDefined soạn isUndefined với một chức năng mà phủ nhận kết quả của isUndefined.

var isDefined = compose(op["!"], isUndefined); 

tương đương với

var isDefined = compose(function(a){return !a;}, isUndefined); 

tương đương với (biến đổi tên cho rõ ràng)

var isDefined = compose(

    function(a){return !a;}, 

    partial( /* partial function becomes 'a' passed to first function */ 
     function(b, c) { 
      return b === c; 
     }, 
     undefined /* undefined becomes 'b' passed to partial */ 
    ) 

)(argumentForisDefined /* argumentForisDefined becomes 'c' passed to partial */); 

Nếu chúng ta nhìn vào những gì chúng tôi có cho đến nay và thay thế để có thể đọc, nắm đối với hàm nhận đối số và so sánh nó với undefined, phủ nhận kết quả và trả về boolean

var isDefined = function (b) { return !undefined === b; } 
+0

OK Tôi nghĩ mình hiểu nhầm lẫn của mình. Tôi đã nhầm lẫn về lý do tại sao function.apply xuất hiện hai lần. Nhưng nếu hàm Compose chỉ là func1 (func2), các đối số (trong trường hợp này là Math.PI hoặc Math.PIE) sẽ không bao giờ được chuyển tới hàm partial. Tôi có đúng không? – Shaan

+0

Đúng vậy - việc soạn sẽ không trả về thành phần hàm của hai hàm mà ban đầu nó được truyền, nhưng sẽ trả lại kết quả ngay lập tức gọi chúng, vì vậy sẽ không có giá trị bổ sung nào cho 'partial'; nó đã được gọi rồi. –

0

Vì vậy, chỉ đơn giản là mổ xẻ nó. Giả sử chúng tôi có chức năng soạn thư này:

function compose(func1, func2) { 
    return func1(func2.apply(null, arguments)); 
} 

Điều gì sẽ xảy ra khi bạn sử dụng nó như thế này?

a = compose(function(){console.log(1)}, function(){console.log(2)}); 

Chức năng thứ hai sẽ được gọi ngay lập tức xuất ra 2, và thẳng sau đó chức năng đầu tiên sẽ được gọi là xuất ra 1. a sẽ là undefined, bởi vì chức năng đầu tiên không trả lại bất cứ điều gì.

Điều bạn muốn kết hợp để làm là trả về một hàm mới, kết hợp hai chức năng khác và bạn có thể gọi theo ý muốn.

Thực hiện trên tất cả trên bản gốc, sẽ trả về một chức năng mới, khi bạn gọi nó là a() sẽ xuất 2 và sau đó 1.