Angel Politis
Angel Politis

Reputation: 11313

Mass create methods for an object

I know that a new method for an object can be declare like so:

var MyObject = function() {return new MyObject.prototype};
MyObject.prototype.exists = function() {alert("The object exists.")};

How can I create many methods as a bunch for MyObject instead of one by one?

I have tried:

MyObject.prototype = {
    exists: function() {alert("The object exists.")},
    isBorn: function() {alert("The object is born.")},
    isDead: function() {alert("The object has left our world.")}
}

Calling MyObject.exists() returns: Uncaught TypeError: MyObject.exists is not a function


What I am trying to do:

I am trying to do something like jQuery does.

jQuery is defined like so:

jQuery = function(selector, context) {included)
    return new jQuery.fn.init(selector, context);
}

We don't say var j = new jQuery; when we call it like jQuery("#foo").

Then the files says:

jQuery.fn = jQuery.prototype = {
    jquery: version,
    constructor: jQuery,
    length: 0,

    toArray: function() {
        return slice.call( this );
    }
    ...
}

Isn't toArray() a method of the jQuery object? Why doesn't it show the same error when I call it.

Upvotes: 0

Views: 170

Answers (3)

Dan Prince
Dan Prince

Reputation: 29989

When the jQuery function is called, you're not creating an instance of jQuery which is why you don't use the new keyword. Instead, you're returning an instance of jQuery.fn.init.

Follow it down and you'll see that the prototype of init being declared:

init.prototype = jQuery.fn;

And the definition for jQuery.fn is:

jQuery.fn = jQuery.prototype = { ... };

Which means that (new jQuery.fn.init(selector, context)) has all the methods from jQuery.prototype.

So, toArray is not a method of the jQuery object, but rather a method on the prototype of the return value from calling jQuery().

You can achieve the same thing in fewer steps by manually assigning the prototype of the return value.

function MyObject() {
  var obj = {};
  return Object.setPrototypeOf(obj, MyObject.prototype);
}

MyObject.prototype.toArray = function() {};

MyObject().toArray();

Upvotes: 1

Tamas Hegedus
Tamas Hegedus

Reputation: 29906

The first one is still better because prototype objects have predefined properties (currently only constructor, but later the standard can be extended), and totally overwriting the prototype object will effectively remove those properties. But still it can be shortened like:

function Foo() {}
const p = Foo.prototype;
console.log(Object.getOwnPropertyNames(p));
p.exists = function() { console.log("exists"); };
p.isBorn = function() { console.log("isBorn"); };

(new Foo).exists();

But hey, it's 2016! We have javascript classes in most major browsers (check compatibility at MDN)!

class Foo {
  exists() { console.log("exists"); }
  isBorn() { console.log("isBorn"); }
}

(new Foo).exists();

Upvotes: 0

isaac9A
isaac9A

Reputation: 903

You were very close, you just have to create a new instance of the object for it to inherit from its own prototype chain.

var myObj = function () {};
myObj.prototype = {
  a: function () { console.log(1) },
  b: function () { console.log(2) },
  c: function () { console.log(3) }
};
var myObject = new myObj();
myObject.a(); // 1
myObject.b(); // 2
myObject.c(); // 3

Upvotes: 0

Related Questions