Why doesn't javascript “this” work with “each”

2019-07-28 23:20发布

I'm trying to assign a class to an element upon detecting that it has a data-voted attribute of "true", but the simple addClass line is not working.

I was using $(this) until I read jQuery's documentation for each(), and then switched to the following:

windowReady = ->
  jQuery -> 
    $voteLinks = $('.vote-button a')

    $voteLinks.each (i, current) ->
      if $(current).data('voted') == "true" 
        $(current).addClass('voted')

$(window).load(windowReady);
$(window).on('page:load', windowReady);

$(this)

windowReady = ->
  jQuery -> 
    $voteLinks = $('.vote-button a')

    $voteLinks.each ->
      if $(this).data('voted') == "true" 
        $(this).addClass('voted')

$(window).load(windowReady);
$(window).on('page:load', windowReady);

But even that is still not assigning a class, even though I've confirmed that it does have the data-voted attribute of "true"

CoffeesSript can be converted to Javascript at js2coffee.

2条回答
太酷不给撩
2楼-- · 2019-07-28 23:50
windowReady = ->
  jQuery -> 
    $voteLinks = $('.vote-button a')

    $voteLinks.each (i, current) ->
      if $(current).data('voted') == true
        $(current).addClass('voted')

$(window).load(windowReady);
$(window).on('page:load', windowReady);

Apparently, there is some flipflopping going on behind the scenes.

The coffeescript normally takes a == and turns it into ===. So according to the ===, it should check for type as well. So when data-voted is "true", you'd think you would have to compare it to "true". NOPE.

Apparently, any data attributed that you reference or obtain via .data(), "true" or "false" gets turned back into boolean true / false.

Thus you have to leave the coffeescript as using ==, which in javascript is actually ===, which checks for the type of variable (needs to be boolean, not a string).

what implicit background craziness. Documentation, documentation, documentation. Lack of it, or not reading it wastes life. Thus documentation saves lives xp

查看更多
家丑人穷心不美
3楼-- · 2019-07-29 00:00

As a complement to the answer by @gwho, this implicit type conversion is in fact a documented feature of JQuery:

HTML5 data-* Attributes

Every attempt is made to convert the string to a JavaScript value (this includes booleans, numbers, objects, arrays, and null). A value is only converted to a number if doing so doesn't change the value's representation. For example, "1E02" and "100.000" are equivalent as numbers (numeric value 100) but converting them would alter their representation so they are left as strings. The string value "100" is converted to the number 100.

[...]

To retrieve the value's attribute as a string without any attempt to convert it, use the attr() method.

As explained in the above quote, if you "don't like" implicit conversion, you might prefer using attr() (using the full attribute name) instead of data():

windowReady = ->
  jQuery -> 
    $voteLinks = $('.vote-button a')

    $voteLinks.each (i, current) ->
      if $(current).attr('data-voted') == "true" 
        $(current).addClass('voted')

And if you can live with that implicit conversion:

windowReady = ->
  jQuery -> 
    $voteLinks = $('.vote-button a')

    $voteLinks.each (i, current) ->
      if $(current).data('voted') == true 
        $(current).addClass('voted')
查看更多
登录 后发表回答