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

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

本文关键字:回调 arguments me 返回 fn apply 函数      更新时间:2024-01-23

这个最近为 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 函数的回调。

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

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

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

我大致了解此功能的工作原理

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

这只是意味着函数fn是在me的上下文中调用的,传递给它的任何参数都由arguments表示,但是,我不明白它在这个应用程序中是如何工作的。为什么它在编译的 JavaScript 中生成,而它不在原始的 coffeescript 中,问题 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;
})();

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

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

它出现在 C 构造函数中,并且随之而来的是用__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 关键字是动态范围的,表示 当前函数附加到的对象。如果您通过 函数作为回调或将其附加到其他对象, this的原始价值将丢失。[...]

胖箭头=>既可用于定义函数,也可用于绑定 它到当前值this,就在现场。这很有帮助 当使用基于回调的库(如 Prototype 或 jQuery(时,对于 创建要传递给 each 或事件处理程序的迭代器函数 与bind一起使用的函数。使用胖箭头创建的函数是 能够访问定义属性的this的属性。

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

something_that_calls_back(obj.each)

并且this调用时each内部obj