function(){return fn.apply(me,arguments);作为回调

时间:2013-12-02 23:50:46

标签: javascript coffeescript

这个最近开源的Monocle.io https://github.com/maccman/monocle源代码有一些我不懂的咖啡脚本/ mvc代码。如果我查看Chrome控制台中的源代码(显示JavaScript,而不是coffeescript),则会在类声明之前的每个连接文件的顶部有一个这样的函数。例如,创建集合的代码的第一部分就像这样

    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

  $ = jQuery;

  Events = require('events');

  Collection = (function() {

然而,在coffeeScript中,这个功能

__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

没有出现。它只显示代码编译为JavaScript的时间。

问题1.为什么该功能仅出现在已编译的JavaScript中?

继续前进,它似乎是相同的功能

 function (){ return fn.apply(me, arguments); } 

作为整个代码中许多不同函数的回调传递。例如,在Collection类中,它是传递给每个函数的回调。

 each: (callback) =>
    @all().promise.done (records) =>
      callback(rec) for rec in records

它也是在Model类中传递给此观察者函数的回调(在应用程序的MVC部分中)

observe: (callback) ->
    @on('observe', callback)

我一般了解这个功能是如何工作的

function (){ return fn.apply(me, arguments); } 

这只意味着在fn的上下文中调用函数me,并且传递给它的任何参数都由arguments表示,但是,我不明白它是怎么回事在这个应用程序中工作当它不在原始coffeescript中时,为什么它在编译好的JavaScript中生成?问题2)是否有一些关于MVC应用程序的东西使它适合作为所有这些不同函数的回调,或者为什么它作为回调传递给所有这些功能

1 个答案:

答案 0 :(得分:2)

让我们看一下CoffeeScript的简化示例:

class C
    m: => console.log(@)

这就是这个JavaScript:

var C,
  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

C = (function() {
  function C() {
    this.m = __bind(this.m, this);
  }

  C.prototype.m = function() {
    return console.log(this);
  };

  return C;

})();

你的__bind。如果我们看看如何使用它,那么事情可能会更清楚:

this.m = __bind(this.m, this);

它出现在C构造函数中,并且用m方法取代__bind方法,因此我们实际上有这个:

var m     = this.m;
var _this = this;
this.m = function() {
    return m.apply(_this, arguments);
};

我们发现m方法的结尾总是this作为C实例,无论它是如何被调用的:

c = new C
c.m() # @ (AKA 'this') is `c` inside `m`.
f = c.m
f()   # @ is again `c` inside `f`
  

Demo(请打开你的控制台)

将其与m: -> console.log(@)的行为进行比较:

  

Demo

您可以在这两个演示链接上看到完整生成的JavaScript。

那么这个-> vs =>的内容是怎么回事?在CoffeeScript中,您使用->=>来定义函数或方法。区别在于=> produces bound functions

  

功能绑定

     

在JavaScript中,this关键字的动态范围是指   当前函数附加到的对象。如果你通过了   作为回调函数或将其附加到不同的对象,   this的原始值将丢失。 [...]

     

胖箭=>可用于定义函数和绑定   它当前就是this的当前值。这很有帮助   当使用像Prototype或jQuery这样的基于回调的库时   创建迭代器函数以传递给each或事件处理程序   与bind一起使用的函数。使用胖箭头创建的函数是   能够访问定义它们的this的属性。

请注意文档该部分中的回调讨论。你看到所有与each绑定的东西,因为有人希望能够说出这样的话:

something_that_calls_back(obj.each)

并在调用thisobjeach