10

I have 2 BI object in different files, now I want to extend the first object with other ones.

1st Object

var BI = BI || {};
BI = {
    firstInit: function () {
        console.log('I am first init');
    }
}

Other file

2nd Object

BI = {
   init: function () {
     console.log('I am init');
   }
}

Now I want 2nd Object should contain the firstInit as well. Let me know I can explain further. I am using jQuery.

cнŝdk
  • 31,391
  • 7
  • 56
  • 78

4 Answers4

3

You can use jQuery's $.extend here.

Try following code

var BI = BI || {};
BI = {
  firstInit: function () {
    console.log('I am first init');
  }
}

$.extend(BI, {
  init: function () {
    console.log('I am init');
  }
});

console.log(BI);

Here is the DEMO

ʞɹᴉʞ ǝʌɐp
  • 5,350
  • 8
  • 39
  • 65
2

Out of the box, you can't do it that easily with good x-browser support.

However, jQuery does give you a means to have objects extend eachother: http://api.jquery.com/jQuery.extend/

So you would do:

var extended = $.extend({}, BI, {
   init: function () {
     console.log('I am init');
   }
});

The first argument (empty object, {}) means that the properties of BI (the second argument) and the object you pass in will be combined in to the new object.

I wrote a small polymorphic extension to $.extend for this purpose which will allow you to extend from multiple objects, with the latter item taking precidence:

mergeObjects = function () {
  // Convert the arguments Array-like object to an actual array
  var args = Array.prototype.slice.call(arguments);

  // Only one item? If we give this to $.extend it'll extend jQuery, which is
  // not the desired result, so let's spit it back verbatim
  if (args.length === 1) {
    return args[0];
  }

  // We need to make sure we're always combining objects starting with a
  // completely empty one
  args.unshift(true, {});
  return jQuery.extend.apply(jQuery, args);
};

So, you can define your base module with common properties like so:

var MyBaseModule.prototype = {
  options: {},
  getOptions: function () {
    return this.options || {};
  },
  setOptions: function (options) {
    this.options = options;
  },
  log: function () {
    // do your logging stuff here
  },
  error: function () {
    // do your error handling stuff here
  }
};

And your actual modules:

var MyModule = function () {
  // constructor code here
};

var MyModule.prototype = mergeObjects(MyBaseModule, {
  // define your module's methods here
});

...now MyModule has "inherited" the options property and options getter and setter. You can instantiate the new module with new MyModule;

If you want a vanilla way of doing it, this post may be useful

BenLanc
  • 2,344
  • 1
  • 19
  • 24
  • 1
    Note that this will create a new object with the properties copied into it rather than extending the first object. – David Hellsing Aug 02 '13 at 13:45
  • 3
    If you can do it with jQ, you can do it _out of the box_, too. There's nothing jQ does, you can't do with VanillaJS – Elias Van Ootegem Aug 02 '13 at 13:45
  • Sure, ECMA5 makes it easier, but there's no quick and easy without rolling your own – BenLanc Aug 02 '13 at 13:49
  • @EliasVanOotegem Cool, can you share any example without using jQuery I would love to know that. However I ll google anyways.. Thanks –  Aug 02 '13 at 13:49
  • 1
    @illumine: `function cloneO(o){ function F(){}; F.prototype = o; return new F;}` uses an object as the prototype of a new object, then add the methods/properties you want to extend the original object with, to the clone. That's all. – Elias Van Ootegem Aug 02 '13 at 13:57
  • *"Out of the box, you can't do it that easily with good x-browser support."* Iterating over the properties of an object with a `for` loop doesn't seem to be very difficult to me. – Felix Kling Aug 02 '13 at 13:59
  • @illumine: Added a vanillaJS function that clones/extends, that can be written in a mere 5 lines of code... it's really not that hard – Elias Van Ootegem Aug 02 '13 at 14:04
0

There are 2 ways of doing this in JavaScript. One is using prototype chaining, the other is to just copy the method. In this case both of your objects have the object as the prototype, so you need to copy the method:

BI2.init = BI1.firstInit;

To copy all methods and attributes in JQuery, use $.extend;

BI2 = $.extend({ init: function () { } }, BI1);
0

In Javascript Functions are objects. So they can be passed as arguments to functions or assigned to other variables (referenced).

var BI = {
    firstInit: function () {
        console.log('I am first init');
    }
};

var BI2 = {
   init: function () {
     console.log('I am init');
   }
}

// copy the reference of function
BI2.originalFirstInit = BI.firstInit;

// run this function
BI2.originalFirstInit(); // output: "I am first init"
Carlos Morales
  • 5,676
  • 4
  • 34
  • 42