0

I am learning JavaScript, and encountered this function on a website. It seems to use jQuery, which I don't have much experience with. I understand the function except for the lines with $.each.

Can you help me rewrite the function without the $.each? I don't understand what it means, even after reading the jQuery documentation. What is it referring to, and how can I rewrite this function to work without jQuery ?

ArraySort = function(array, sortFunc){
              var tmp = [];
              var aSorted=[];
              var oSorted={};

              for (var k in array) {
                if (array.hasOwnProperty(k)) 
                    tmp.push({key: k, value:  array[k]});
              }

              tmp.sort(function(o1, o2) {
                    return sortFunc(o1.value, o2.value);
              });                     

              if(Object.prototype.toString.call(array) === '[object Array]'){
                  $.each(tmp, function(index, value){
                      aSorted.push(value.value);
                  });
                  return aSorted;                     
              }

              if(Object.prototype.toString.call(array) === '[object Object]'){
                  $.each(tmp, function(index, value){
                      oSorted[value.key]=value.value;
                  });                     
                  return oSorted;
              }               
     };
halfer
  • 19,824
  • 17
  • 99
  • 186
Rahul Iyer
  • 19,924
  • 21
  • 96
  • 190

3 Answers3

3

You can update your code from

$.each(tmp, function(index, value){
    aSorted.push(value.value);
});

to

for (var i = 0; i < tmp.length; i++) {
     aSorted.push(tmp[i].value);
}

Similarly, you can achieve the same for other $.each by updating to following

for (var i = 0; i < tmp.length; i++) {
    var obj = tmp[i];
    oSorted[obj.key] = obj.value;
};      

Note: tmp is sorted. You can return tmp only and then iterate on it and get tmp.value or tmp.key.

Nikhil Aggarwal
  • 28,197
  • 4
  • 43
  • 59
  • 2
    only half the answer, the second $.each is different from the first 'cause it maintains the current keys... – patrick Jul 11 '15 at 10:19
  • @patrick - I believe OP could have done it by itself as on how to extract data. Though, I have updated the answer for second $.each as well. Just to be clear, tmp is an array of object with properties key and value. – Nikhil Aggarwal Jul 11 '15 at 10:33
  • there is something wrong with the change you made, because now the array is full of 0's. – Rahul Iyer Jul 11 '15 at 10:44
  • @John - I have reverted the change. Please check. Also, I would wish to further analyze the issue. – Nikhil Aggarwal Jul 11 '15 at 10:48
  • Its hard for me to verify, because I didn't understand how $.each works in the first place. I just know that depending on how you changed the second $.each, I got different answers both times. And neither time did it match the result of the jquery – Rahul Iyer Jul 11 '15 at 10:50
  • @John: *"because I didn't understand how $.each works in the first place"* Well, [there's a solution to that](http://api.jquery.com/jQuery.each). – T.J. Crowder Jul 11 '15 at 10:55
  • @T.J.Crowder As I mentioned earlier, I did read that exact page, but don't understand. Which is why I posted my question here! XD – Rahul Iyer Jul 11 '15 at 10:56
  • @nikhil: Actually, I'm wrong, `tmp` is always an array. It's `array` which may or may not be an array! – T.J. Crowder Jul 11 '15 at 10:56
  • ECMAScript 5 (which is the standard on which current browser JavaScript implementations are based) simply doesn't allow for ordered object properties. – Nikhil Aggarwal Jul 11 '15 at 11:02
  • 1
    @nikhil: True, but [ES6 introduces object property order](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys) and V8 (apparently the OP is trying to use this in Node) along with most (not all!) other major engines already supports that order. Your answer's been correct for over an hour now, apologies for my earlier misread that made me think it wasn't. – T.J. Crowder Jul 11 '15 at 11:34
2

In both cases, $.each is just being used to loop through the array entries in tmp.

This answer has an exhaustive list of your options for looping through array entries in JavaScript without using any libraries. With current browsers, the usual way would be Array#forEach:

tmp.forEach(function(value, index) {
    // ...
});

Note that the arguments to the callback are in a different order. But again, other options are listed in that other answer. In fact, when using forEach, we don't need the index arugment, as the code in your $.each loops isn't using it, it's just there because it's the first argument and the code wants the second (value). So we can leave it off:

tmp.forEach(function(value) {
    // ...
});

In each place $.each was used in your original code, if you just drop the body of the $.each call into the above where I have // ..., it will do the same thing $.each was doing.

So for the first call (in the === '[object Array]' branch), that looks like this:

tmp.forEach(function(value){
    aSorted.push(value.value);
});

For the second call (in the === '[object Object]' branch), that looks like this:

tmp.forEach(function(value) {
    oSorted[value.key]=value.value;
});

While the above would be sufficient to get rid of $.each, here's a completely rewritten version with explanatory text:

ArraySort = function(array, sortFunc){

    // If `array` is an array, this is trivial: Copy it and use `Array#sort`
    // (since the original created a copy)
    if (Array.isArray(array)) {
        return array.slice().sort(sortFunc);
    }

    // If `array` is not a plain object, return `undefined`
    // (This is effectively what the original did, by simply
    // falling off the bottom of the function.)
    if (object.prototype.toString.call(array) !== "[object Object]") {
        return undefined;
    }

    // Create a "sorted" version of the object.
    // NOTE!!! In the current version of JavaScript, object properties HAVE
    // NO ORDER. At all. None. However, in the next version of JavaScript,
    // ECMAScript6 (aka "ES6"), they will have an order, and V8 (the engine
    // in NodeJS) already supports that order. The order is based on the
    // order in which the properties were created (but it's more complicated
    // that that, see:
    // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys

    // Get an array of objects with `key` being the property name and
    // `value` being its value.
    var tmp = Object.keys(array).map(function(key) {
        return {key: key, value: array[key]};
    });

    // Sort `tmp` according to `sortFunc` on its values
    tmp.sort(function(o1, o2) {
        return sortFunc(o1.value, o2.value);
    });

    // Create and return a new object with the properties in that order (see
    // caveat above!!)
    var result = {};
    tmp.forEach(function(entry) {
        result[entry.key] = entry.value;
    });
    return result;
};

Here's that link about property order: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
-1

You're right, it's jQuery. it meant: "for each element in object tmp do the function" is what it means.

I would not try to convert this to javascript, I would take the extra step and learn jQuery though, it's very VERY powerful!

in Javascript:

for(var i = 0; i < tmp.length ; i++){
  aSorted.push(tmp[i].value);
}

and the second $.each

for(var i in tmp){
  oSorted[i]=tmp[i].value;
}
patrick
  • 11,519
  • 8
  • 71
  • 80
  • your syntax is incorrect. you have broken parentheses. – Rahul Iyer Jul 11 '15 at 10:24
  • I think there is something wrong because now the function doesn't work properly. – Rahul Iyer Jul 11 '15 at 10:26
  • Wow... instead of downvoting you should fix those parentheses John... Parenthesis in the first script are fine... fixed the ones in the second example... But downvoting people pointing out what you're looking for... wow... – patrick Jul 11 '15 at 11:52
  • @ patrick - Never assume that the person commenting and the person downvoting are the same person unless they say they are. You'll be wrong much more often than you're right. – T.J. Crowder Jul 11 '15 at 14:21
  • T.J., you're right, sorry... Curse the one who downvoted than, Jon, I'll take back my acquisition. Jumped to conclusions. Cursed the one that downvoted though, this here is a valid answer, nothing wrong with it – patrick Jul 12 '15 at 16:04
  • Worth noting that `for-in` is not for looping through array entries, though. More [here](http://stackoverflow.com/questions/9329446/for-each-over-an-array-in-javascript/9329476#9329476). – T.J. Crowder Jul 13 '15 at 21:37
  • True T.J., I'll edit the code to reflect the right loops – patrick Jul 14 '15 at 00:54