CoffeeScript:如何同时使用胖箭头和 this?

Posted

技术标签:

【中文标题】CoffeeScript:如何同时使用胖箭头和 this?【英文标题】:CoffeeScript: How to use both fat arrow and this? 【发布时间】:2012-09-20 19:42:42 【问题描述】:

我有一个咖啡脚本类,它有一些 jquery 事件监听器。我想使用粗箭头=> 来避免引用该类,但我仍然需要引用通常与this 一起使用的元素。如何同时使用两者?

class PostForm
    constructor: ->
        $('ul.tabs li').on 'click', =>
            tab = $(this)
            @highlight_tab(tab)
            @set_post_type(tab.attr('data-id'))

    highlight_tab: (tab)->
        tab.addClass 'active'

    set_post_type: (id) ->
        $('#post_type_id').val(id)

【问题讨论】:

你能多描述一下你想做什么吗?你想在哪里使用(这个),上面的哪一部分没有按照你想要的方式工作? IOW,您希望 this 引用什么对象?事件的目标,PostForm 类实例等? 【参考方案1】:

CoffeeScript 将this@ 链接到外部上下文,因此您无法访问 jQuery 提供的上下文(也就是所需的“this”)。请改用event.target

class PostForm
    constructor: ->
        $('ul.tabs li').on 'click', (event) =>
            tab = $(event.target)
            @highlight_tab(tab)

【讨论】:

event.target 也将我们保存在 Backbone.js event.target 对于不了解 this 周围的 DOM 规则的人来说也不那么令人困惑 请注意,如果您使用选择器执行事件,您可能需要 evt.currentTarget。见codepen.io/ddopson/pen/erLiv 你在 d3 上做什么? d3 中的回调给你对象(不是 DOM) 我不知道你写的时候是不是真的,但是 event.target 有时会返回一个与 'this' 不同的元素。点击事件回调中的“this”返回触发回调的元素,而 event.target 返回触发点击事件时鼠标所在的元素(通常是某种子元素)【参考方案2】:

使用 evt.currentTarget

您可能应该使用evt.currentTarget(相当于this)而不是evt.target(不是)。如果您为click 通知而点击的节点具有子节点,则evt.target 可能是这些子节点之一,而不是您添加click 处理程序的节点。

有关此行为的演示,请参阅 http://codepen.io/ddopson/pen/erLiv。 (点击内部红色框可以看到currentTarget指向红色div,而target指向外部蓝色div,事件处理程序注册在上面)

$('ul.tabs li').on 'click', (event) =>
  tab = $(event.currentTarget)
  @highlight_tab(tab)

回答所提问题 - 获取 `=>` 和 `this`:

您可以执行以下操作...

$('ul.tabs li').on 'click', (event) =>
  tab = $(` this `)     # MAKE SURE TO ADD THE SPACES AROUND `this`
  @highlight_tab(tab)

这些空格很关键,因为它们可以防止 Coffee 将 this 咀嚼成 _this

使用`self`和`->`

或者,执行以下操作...

self = this
$('ul.tabs li').on 'click', (event) ->
  tab = $(this)
  self.highlight_tab(tab)

这类似于 CQQL 的答案,只是我更喜欢习惯使用 self 作为变量名;我的 VIM syntax highlighting rules color self 作为一个“特殊”变量,就像 thisargumentsprototype 一样。

【讨论】:

self = 这正是我所做的。效果很好! event.currentTarget 实际上与“this”不同,至少对于点击事件的 jquery 而言。它有时可能具有相同的值,但也可能不同,具体取决于具体情况。 'this' 指的是被点击的元素,而 event.currentTarget 返回正在监视点击事件的元素。 @GlyphGryph - 感谢您的澄清!【参考方案3】:

我更喜欢这个版本,因为我更容易理解。

class PostForm
    constructor: ->
        post_form = this

        $('ul.tabs li').on 'click', (event) ->
            tab = $(this)
            post_form.highlight_tab(tab)

【讨论】:

你将如何从课堂上的另一个函数访问 post_form? 类方法应该可以正常使用this来引用PostForm的当前实例。 谢谢@CQQL :) 我详细说明了我的问题,并给出了我最终得出的答案。最初我想将回调函数直接交给 click 处理程序,但后来意识到我应该首先将其包装在一个匿名函数中,该函数获取 this 并通过 self 将其传递给命名函数,以便获得最好的两个世界。【参考方案4】:

您可能希望从您的函数访问构造函数中设置的变量。这就是你的做法(关键是通过self 调用函数,同时先用细箭头提取this):

class PostForm
    constructor: ->
        self = this

        @some_contrived_variable = true

        $('ul.tabs li').on 'click', ->
            tab = $(this)
            self.highlight_tab(tab)
            self.set_post_type(tab.attr('data-id'))

    highlight_tab: (tab) ->
        # Because of the fat arrow here you can now access @ again
        if @some_contrived_variable
            tab.addClass 'active'

    set_post_type: (id) ->
        $('#post_type_id').val(id)

顺便说一句:This is a great explanation of when to use the fat and thin arrow.

总结:

    你在函数中使用这个 (@) 吗? 您想稍后执行该函数,可能从不同的范围执行吗?

【讨论】:

您可以在highlight_tab 中访问@,因为highlight_tabself 上被调用,而不是因为粗箭头。胖箭头没有任何区别。您可以通过编译这两个版本自己尝试。

以上是关于CoffeeScript:如何同时使用胖箭头和 this?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 CoffeeScript 胖箭头回调中引用实际的“this”?

如何将胖箭头AngularJS转换为coffeescript

如何使用咖啡脚本使用`this`和`_this`(胖箭头)?

JavaScript ES6箭头函数指南

如何配置ESLint以允许胖箭头类方法

在javascript中使用严格不适用于胖箭头?