6

I have added the following method to the Array prototype:

Array.prototype.foreach = function(func){
    for(var i = 0; i < this.length; i++){
        if(!func(this[i]) === false) break; //return false from func in order to break the loop
    }
    return this;
}

In the same file, after the above code, I have the following jQuery plugin:

jQuery.fn.addClassForEvents = function(){

    var that = this;

    arguments.foreach(function(event){
        that.bind(event[0], function(){
            that.addClass(event[0]);
        })
        .bind(event[1], function(){
            that.removeClass(event[0]);
        });
    });

    return this;
}

In order to use this jQuery plugin, my code would look something like:

$('div').addClassForEvents(['mouseenter', 'mouseleave']);

However, the browser throws an error on the "arguments.foreach(...." line of the jQuery plugin, stating simply that

Object # has no method 'foreach'

Yet the foreach method works in other places of my code. Why is it undefined within this jQuery plugin?

7
  • 1
    Why do you break your loop (and foreach), when the function returns a truthy value? Commented Jan 29, 2012 at 13:48
  • That's actually a mistake (just look at my comment next to that line of code!). Thanks for pointing it out. Commented Jan 29, 2012 at 14:48
  • That still does not make much sense within a foreach function/method.… Commented Jan 29, 2012 at 16:35
  • Why is that? Seems like providing a way to break out of a loop is pretty standard. Commented Jan 29, 2012 at 17:08
  • Common understanding is that foreach iterates over every element of a collection. I don't know of a language, where a foreach method breaks out if the applied function returns false. Feel free to prove me wrong Commented Jan 29, 2012 at 17:53

4 Answers 4

8

It doesn't work because arguments isn't an array. Its an (array-like) arguments object.

Explanation from Mozilla

You can convert it to an array using slice in modern browsers (and by actually looping in IE).

var argArray = Array.prototype.slice.call(arguments)
Sign up to request clarification or add additional context in comments.

2 Comments

You can convert it to an array using slice in IE too
@AngusC You could be correct. I have a generic function that does this and there are definitely some array-like objects that IE doesn't like to call slice on.
4

arguments is not an array, but an object. For example it provides properties such as arguments.callee and arguments.caller.

You can use foreach of the Array prototype by calling apply on it (cf. The JavaScript arguments object…and beyond):

Since all the methods of Array.prototype are designed to be generic they can be easily applied to the array-compatible arguments object:

jQuery.fn.addClassForEvents = function(){

    var that = this;

    [].foreach.apply(arguments, (function(event){
        that.bind(event[0], function(){
            that.addClass(event[0]);
        })
        .bind(event[1], function(){
            that.removeClass(event[0]);
        });
    });

    return this;
}

Comments

2

You need to turn the arguments object into an array

Try this:

jQuery.fn.addClassForEvents = function(){

    var that = this, arg = Array.prototype.slice.call(arguments);

    arg.foreach(function(event){
        that.bind(event[0], function(){
            that.addClass(event[0]);
        })
        .bind(event[1], function(){
            that.removeClass(event[0]);
        });
    });

    return this;
}

Comments

0

To convert the arguments to an array, you can use the jQuery.makeArray(arguments) too...

http://api.jquery.com/jQuery.makeArray/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.