5

I want to add the ability to extend javascript objects by adding a method to the prototype.
The method will receive one or more other objects and will add all of the key/values to this.
This is what I came up with:

Object::extend = (objects...) ->
    @[key] = value for key, value of object for object in objects

or this:

Object::extend = (objects...) ->
    for object in objects
        for key, value of object
            @[key] = value 

Both work as expected, and compile into the same javascript code:

var __slice = [].slice;

Object.prototype.extend = function() {
  var key, object, objects, value, _i, _len, _results;
  objects = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  _results = [];
  for (_i = 0, _len = objects.length; _i < _len; _i++) {
    object = objects[_i];
    _results.push((function() {
      var _results1;
      _results1 = [];
      for (key in object) {
        value = object[key];
        _results1.push(this[key] = value);
      }
      return _results1;
    }).call(this));
  }
  return _results;
};

What I'm not too happy about is the whole results thing that is created per for loop which is completely redundant for my purpose.
Is there a way to get a code more like:

Object.prototype.extend = function() {
  var key, object, objects, value, _i, _len;
  objects = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  for (_i = 0, _len = objects.length; _i < _len; _i++) {
    object = objects[_i];
    (function() {
      for (key in object) {
        value = object[key];
        this[key] = value;
      }
    }).call(this);
  }
};

Thanks.


Edit

I'm aware that I can simply embed javascript code, but looking for a coffeescript solution.

5
  • Have you noticed the coffeescript tag? The javascript code is the result of compiling coffeescript into javascript, I did not write that js code. Commented Jun 8, 2012 at 0:38
  • Just noticed that and removed my comment immediately... Oops. Commented Jun 8, 2012 at 0:39
  • Yuck, modifying Object.prototype Commented Nov 15, 2012 at 18:19
  • Yeah, I know, this was just to test a few things Commented Nov 15, 2012 at 22:05
  • The code above can be updated with a check for properties object's only and leave the properties inherited from prototype away. JSFiddle Commented May 6, 2014 at 13:14

1 Answer 1

4

You can try adding an explicit return:

Object::extend = (objects...) ->
    for object in objects
        for key, value of object
            @[key] = value
    return 

That produces this:

var __slice = [].slice;

Object.prototype.extend = function() {
  var key, object, objects, value, _i, _len;
  objects = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  for (_i = 0, _len = objects.length; _i < _len; _i++) {
    object = objects[_i];
    for (key in object) {
      value = object[key];
      this[key] = value;
    }
  }
};

Every CoffeeScript function returns the value of the last expression in the function, CoffeeScript loops are also expressions. That means that CoffeeScript has to build all that _results stuff to produce a return value for your function since you had an implicit return applying to the outer loop. If you remove that implicit return by adding an explicit "return nothing" then the CS→JS compiler seems to be smart enough to not do all that extra _results work.

Sign up to request clarification or add additional context in comments.

2 Comments

Great! This is exactly what I was looking for! Though I went with my first version. Thank you.
It is better to return @ in the end to make possibility of chain calls .

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.