0

I'm going through the peepcode jQuery example (https://peepcode.com/products/jquery) and I chose to update all the dependencies.

Not surprisingly, I ran into an issue concerning the difference between string literals and String objects in javascript (great discussion here: Why are there two kinds of JavaScript strings?)

One problem I'm hitting is that jQuery.each converts string literals to String objects, which the jQueryUI method removeClass does not handle properly. Here is a code snippet that fixes the issue.

I'd like to know if the bug is in jQuery.each incorrectly converting string literals to String objects or should removeClass assume that it could get either a string literal or a string object.

Update: I just realized that here's another workaround: Strings in array are no longer strings after jQuery.each()

Here's the code:

jQuery.fn.extend({
    taskStates:["task-empty", "task-x", "task-apostrophe", "task-dash"],

    resetTaskStateClassNames: function() {
        var elements = this;
// Commented code breaks as "this" becomes the String object not the literal
// and removeClass does not check for String Object
//        jQuery.each(jQuery.fn.taskStates, function(){
//            elements.removeClass(this); // this is the taskState
//        })
        jQuery.fn.taskStates.forEach( function(ts) {
            elements.removeClass(ts);
        });
        return this;
    },
Community
  • 1
  • 1
justingordon
  • 12,553
  • 12
  • 72
  • 116

2 Answers2

2

This has nothing to do with jQuery. The value of this in non-strict mode is coerced to an object as if by Object(this).

http://es5.github.com/#x10.4.3

10.4.3 Entering Function Code # Ⓣ

The following steps are performed when control enters the execution context for function code contained in function object F, a caller provided thisArg, and a caller provided argumentsList:

  1. If the function code is strict code, set the ThisBinding to thisArg.
  2. Else if thisArg is null or undefined, set the ThisBinding to the global object.
  3. Else if Type(thisArg) is not Object, set the ThisBinding to ToObject(thisArg).
  4. Else set the ThisBinding to thisArg.
Community
  • 1
  • 1
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
0

This is the jQuery code snippet that works. I guess the API (http://api.jquery.com/jQuery.each/) changed since the screencast was made.

       jQuery.each(jQuery.fn.taskStates, function(index, value){
           elements.removeClass(value); // this is the taskState as a string literal
       })

Besides the fact that you can jQuery.each on either object properties or arrays, I'm don't see any advantage over simply using the javascript forEach

justingordon
  • 12,553
  • 12
  • 72
  • 116