Javascript 函数(){return fn.apply(me,arguments);}作为回调

Javascript 函数(){return fn.apply(me,arguments);}作为回调,javascript,coffeescript,Javascript,Coffeescript,最近Monole.io的开源代码中有一些我不理解的coffee脚本/mvc代码。如果我查看Chrome控制台中的源代码(它显示JavaScript,而不是coffeescript),在每个连接文件的顶部,就在类声明之前,有这样一个函数。例如,创建集合的代码的第一部分如下 __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; $ = jQuery; Events =

最近Monole.io的开源代码中有一些我不理解的coffee脚本/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); } 
在整个代码中作为回调传递给许多不同的函数。例如,在集合类中,它是传递给each函数的回调

 each: (callback) =>
    @all().promise.done (records) =>
      callback(rec) for rec in records
它也是传递给Model类(在应用程序的MVC部分)中的这个观察者函数的回调

我大致了解这个函数是如何工作的

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

这仅仅意味着函数
fn
是在
me
的上下文中调用的,传递给它的任何参数都由
参数表示,但是,我不理解它在这个应用程序中是如何工作的。为什么它不是在原始coffeescript中生成的,而是在编译的JavaScript中生成的,问题2)MVC应用程序中是否有一些东西使它适合作为所有这些不同函数的回调,或者为什么它作为回调传递给所有这些函数?

让我们看一个简化的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;

})();
这是您的
\u绑定
。如果我们看看它是如何使用的,那么事情可能会更清楚:

this.m = __bind(this.m, this);
它出现在
C
构造函数中,它用
\u bind
返回的函数替换
m
方法,因此我们有效地实现了:

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`
(请打开控制台)

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

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

那么这个
->
=>
的东西到底是怎么回事?在CoffeeScript中,使用
->
=>
定义函数或方法。区别在于:

函数绑定

在JavaScript中,
this
关键字的作用域是动态的,表示 当前函数附加到的对象。如果你通过考试 函数作为回调函数或将其附加到另一个对象
的原始值将丢失。[……]

胖箭头
=>
既可用于定义函数,也可用于绑定 将其设置为当前值
,即在现场。这很有帮助 使用基于回调的库(如Prototype或jQuery)时 创建要传递给每个
或事件处理程序的迭代器函数 与
bind
一起使用的函数。使用fat箭头创建的函数如下所示: 能够访问定义此的属性

请注意文档中该部分对回调的讨论。你看到了
每个
的所有绑定内容,因为有人希望能够说:

something_that_calls_back(obj.each)

调用时,将
this
be
obj
放入
each

谢谢您的解释。有点帮助。然而,这就是我在JS中迷失的地方。当我打开这些链接时,我在控制台中寻找什么。控制台中不会自动显示任何内容。我遗漏了什么吗?试着在演示中点击Run按钮。你知道多少JavaScript?好吧,我想我知道了。我应该将一个控制台中的
run
的结果(胖箭头保留上下文)与另一个控制台中的
run
的结果(普通箭头丢失上下文)进行比较,因此在胖箭头中我得到
C{m:function,m:function}
,但使用普通箭头,我得到的窗口作为上下文
窗口{top:Window,Window:Window,location:location,external:Object,chrome:Object…}
。我读过很多JavaScript书籍和应用程序,但在复杂的应用程序中遇到困难,因此即使我理解这些基本点,我也很难在大型应用程序中跟踪这些细节。最基本的是,JavaScript函数中的
取决于函数的调用方式,而不是函数的定义方式。当然,除了当然,在绑定函数的情况下。这就是为什么
c.m()
f()
->
版本中有不同的行为,即使
c.m
f
是完全相同的函数。
something_that_calls_back(obj.each)