2

我正在閱讀John Resig的Javascript忍者祕訣,並嘗試使用其中一個關於咖喱和pariting功能的示例。代碼如下:javascript and currying

<html> 
<body> 
<button id="test">Click Me!</button> 
</body> 


<script type="text/javascript"> 
    Function.prototype.curry = function() { 
     var fn = this, 
     args = Array.prototype.slice.call(arguments); 

     return function() { 
      return fn.apply(this, args.concat(
       Array.prototype.slice.call(arguments))); 
      }; 
     }; 


    var elem = document.getElementById("test"); 
    var bindClick = elem.addEventListener.curry("click"); 
    bindClick(function(){ console.log("OK"); }); 
</script> 
</html> 

但是,下面的代碼似乎產生錯誤遺漏的類型錯誤:在應用函數調用非法。

我似乎無法找出原因,因爲它似乎都有道理。 bindClick將返回與window作爲函數上下文(this)調用函數elem.addEventListener匿名函數和變量將是["click", function() {console.log("OK"); }]

+0

其實,[這不是曲線/schönfinkeling,但部分應用](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application) – Bergi 2013-03-22 09:54:04

+0

hmm。我讀了一些關於差異的文章。但我仍然有點困惑。部分應用程序返回一個函數,其功能與您傳入的函數相似,但其中的參數較少,其他參數已「綁定」。所以,這確實是部分應用。不過,我不明白爲什麼它不會捲曲?好像John Resig在「JS忍者的祕密」和Douglas Crawford的「JS:The Good parts」中定義了相同的功能並將其命名爲「咖喱」。 – henrybai 2013-03-22 10:15:38

回答

3

的問題是,你已經失去了元素的上下文。該addEventListener方法有一個元素上被調用,但是你調用它的函數:

// Here, `this` refers to a function, not an element 
return fn.apply(this, args.concat(Array.prototype.slice.call(arguments))); 

您需要的元素傳遞給你的新功能。例如:

Function.prototype.curry = function() { 
    var fn = this, 
    args = Array.prototype.slice.call(arguments); 

    return function (context) { 
     return fn.apply(
      context, 
      args.concat(Array.prototype.slice.call(arguments, 1)) 
     ); 
    }; 
}; 

這是working example。注意爲返回的函數添加了一個context參數,並且還注意到slice調用中增加了第二個參數 - 需要刪除新的context參數,並且僅應用以下任何參數。

+0

哦,好吧。謝謝.. :)只是澄清,你提到'this'是指一個函數。我想這是因爲它是由fn方法調用的?因此,由於fn引用addEventListener函數,即使匿名函數的this(由bindClick()函數調用)引用window對象,this也會引用addEventListener方法。 – henrybai 2013-03-22 09:51:48

+1

@henrybai - 正確。但是你需要'this'來引用一個元素,否則'addEventListener'將不會有任何實際應用。 – 2013-03-22 09:54:33

+0

@henrybai:是的,在'curry'中''this'指的是addEventListener函數 - 並且被賦值爲'fn',因爲我們不能夠在匿名函數中再使用'this'。 順便說一句,它會更容易使用'綁定':'var bindClick = elem.addEventListener.bind(elem,「click」);' – Bergi 2013-03-22 09:57:55