When to use Object.prototype / JavaScript instance methods - javascript

JavaScript defines Object.prototype as a way to define methods or properties for class-like objects.
A big problem that exists when using Object.prototype is the incorrect behavior when a method is invoked via a callback as this will have the invoking context.
function Foo() {}
Foo.prototype.resize() {
console.log(this);
}
var foo = new Foo();
window.on('resize', foo.resize);
So to work around this limitation we can do the following.
function Foo2() {
function resize() {
console.log(self);
}
var self = this;
this.resize = resize;
}
var foo2 = new Foo2();
window.on('resize', foo2.resize);
Given the above situation, it seems like it's better to always define class-like objects in example 2.
Thus, when should we use the Object.prototype facilities? I mean, you cannot know a priori how your methods will be called, and most certainly you would want the correct this context reference when invoked.
Supporting context: I thought of this question as it seems like you are creating instance methods using Object.prototype. However, as illustrated, you are not. You are simply creating methods that have no "real" connection to their instance. Hence the need to use closure to create an instance-bound method. Furthermore, this question was thought of after reading this excellent explanation of this.

Your confusion comes from the fact that you view JavaScript objects as having methods like in OOP languages. And so you believe they should have fixed context, since methods in OOP languages usually use "early binding" and so they are bound to the correct context. It's different in JavaScript. It's sort of "late binding", when the context of the function - this - is determined when the function is executed. To me, it's beneficial to see methods as simply object properties pointing to a function, that indeed can be executed in different contexts. For example, we could have something like this:
function resize() {
console.log(this);
}
resize.call(window);
resize.call(custom);
If you want, certainly you can achieve "early binding" using bind for example:
function O() {
this.resize = function() {}.bind(this);
}
var o = new O();
But that limits re-usability of the object methods. For example, this wouldn't be possible:
Array.prototype.slice.call(arguments)
You can read here for some suggestions on why methods are not bound even in ES6.
Prototypes are not static methods, they are created to enable memory efficient code reuse. As JLRishe pointed out, the biggest advantage of prototypes is memory usage reduction, since you can define one instance of a function on prototype, and have convenient access to it as object property that have the prototype in their prototype chain. But the prototype is just for convenience. Here is the example with resize without prototype:
// here only one instance of `resize` function is created
function resize() {
console.log(this);
}
var o1 = {
resize: resize
}
var o2 = {
resize: resize
}
You are simply creating methods that have no "real" connection to
their instance.
Correct, here is the example of a prototype with "methods" later to be used with different contexts:
var prototype = {
resize: function() {
console.log(this);
}
}
var o1 = {
resize: resize
}
Object.setPrototypeOf(o1, prototype);
var o2 = {
resize: resize
}
Object.setPrototypeOf(o2, prototype);
I think JavaScript was built with idea in mind that functions are first-class objects, not that objects should have methods with correctly bound context.
Static methods are usually implemented as properties on function constructors, like this:
function SomeObjectConstructor() {}
SomeObjectConstructor.someStaticMethod = function() {}

I think that directly binding an object's method to an event handler, while possible, is a shortcut you want to avoid.
window.on('resize', function () {
foo.resize();
});
Even though it's more verbose, I think writing your handlers like this is clearer and wont affect the context of this in your Object.prototype methods.
As stated in one of the comments, using the object's prototype is more efficient than defining methods for each instance of your object.

Related

Get class methods from a javascript function

Let's say I have a function, and I need to check if it has a class method of a certain name. For example:
function Foo() {
this.bar = function() {
console.log("I am bar!");
}
}
And I want to check if the Foo class actually has the bar method.
I can create a new instance of Foo and then check it, I was just wondering if there was a better way to do this.
I can create a new instance of Foo and then check it, I was just wondering if there was a better way to do this.
No, not if the method is added in the constructor as in your example. There's nothing to check until you create an instance. (Well, except the source code of the constructor function, as Pointy points out in a comment.)
If it were defined on Foo.prototype, it would be a different matter:
function Foo() {
}
Foo.prototype.bar = function() {
console.log("I am bar!");
};
Then you could check by looking for Foo.prototype.bar.
Side note: Calling them "class methods" is likely to confuse people. In class-based OOP, a "class method" is usually one that's not specific to instances, as opposed to being one that's specific to instances but defined by the class. And of course, JavaScript doesn't have class-based OOP (it has prototypical OOP instead, even as of ES6 which adds more class-like trappings).
There is no method until you do:
var x = new Foo();
So, you will have to do that and then test:
if (typeof x.bar === "function")
If your code was using the prototype for the bar method, then you could test the prototype directly without constructing an object, but since the method is only created inside the constructor, you have to run the constructor in order to see it.
TJ Crowder is correct in that you cannot examine the constructor to examine if the "class" Foo has a certain method. However, you can do this:
function Foo() { /* Constructor */ }
Foo.prototype.bar = function() { /* Whatever you want */ }
Then to test, you can simply do typeof Foo.prototype.bar === "function".
There are various advantages and disadvantages to this approach. (See Use of 'prototype' vs. 'this' in JavaScript?). If you really need to test if a certain constructor's instances will inherit a method, you can use the prototype approach.

Get the object that calls a function belonging to one of its properties OR namespacing prototypes?

(Obviously I'm not sure what the title of this should be.)
I'd like to be able to modify the prototypes of native objects with minimal risk (because trust me; I have heard over and over again how it's a mortal javascript sin).
My train of thought goes something like this: I can greatly reduce the possibility of conflicts if I can add my custom functions to a single object on a prototype rather than directly adding them to the prototype itself.
If I have the code,
String.prototype.foo = function() {
//do stuff
};
...obviously the keyword this references the string that called it. However, if I do something like,
String.prototype.foo = {};
String.prototype.foo.bar = function() {
//do stuff
};
...the keyword this references the object foo.
If there some way to overcome this?
The only way to overcome this would be to override the context using call:
String.prototype.foo.bar.call('hello'))
which works, but is pretty ridiculous.
You're better off (as you've already heard) avoiding modifying native prototypes, and instead having an object with your methods accepting the string as a parameter.
Well, there's a couple of ways to do this, depending on how much work you want to put in.
Using bind is the most straightforward way, but you have to define the string as a variable so you can pass a reference of it to bind:
String.prototype.foo = function() { console.log(this); }
String.prototype.foo.bar = function() { console.log(this); }
var g = "hi there";
g.foo() // Yields g
g.foo.bar() // Yields String.prototype.foo()
g.foo.bar.bind(g)() // Yields g again.
There may be another very hackish way to produce the desired result by creating getters and setters on String.prototype.foo so that String.prototype.foo.bar activates a function that returns a function bound to the instance that foo refers to. ??? Confusing.
What might be the best solution to reduce the possibility of conflicts, is to take advantage of prototypal inheritance and create your own sub prototype of the native String.
function MyString(string) {
this.foo = function() { //whatever };
this.foo.bar = (function() {}).bind(this);
this.toString = function() { return string; } // because toString is not generic.
}
MyString.prototype = new String();
Here, you're creating your own "sub-prototype" of the String prototype. It inherits all the properties of the String prototype and adds its own, all without altering the native strings at all. BONUS: this.foo and this.foo.bar will both refer to your instance.
var instance = new MyString("hi");
instance.foo(); // this == instance
instance.foo.bar(); // this == instance
instance.replace("i", "e"); // returns "he"
This maybe wasn't the answer you were looking for, but hopefully it will at least be helpful.

Will defining functions within the constructor consume more memory than attaching it to prototype?

This would presumably be the safest way (Case A):
var myClass = function() { };
myClass.prototype = {
doSomething : function() { alert('Something'); }
};
This is the alternative (Case B):
var myClass = function() {
this.doSomething = function() { alert('Something'); };
};
I'm under the impression that by doing this as shown in Case B, doSomething would be a member, and the function would be defined once for each myClass object I instantiate so that it will exist 100 times in memory for 100 instances, whereas in Case A the function will only exist in one place in memory and different instances will merely reference the prototype.
Am I understanding this correctly?
As a bonus question: When doing it as in Case B, chrome developer gives me intellisense for doSomething, but I must expand __proto__ for an instance to see it. How come it doesn't show up on the object itself? That is, why doesn't prototype members show on the object, but get stuck back down on __proto__? I would have preferred if the __proto__ stack would get flattened and show up on the object directly. Is there another Case that will allow this to happen?
Firstly, in case B, you are merely creating a global function, not attaching it to the instance. You meant:
this.doSomething = function() { }
Secondly, the first will be faster. Though I can't find the link now, jQuery honcho John Resig did a detailed blog post on this showing speed tests on prototypal inheritance of methods vs. methods declared on the instance. Inheritance was notably faster.
In terms of ethos, I've always much favoured inheritance. This is the place for reusable, cross-instance functionality. Adding it to each instance has the sole benefit of allowing you to declare methods inside a single, convenient closure, in your constructor, but that's it.
If this is your reason for liking pattern B, it's possible to do this whilst still a) having the methods inherited; b) not redeclaring them at every instantiation.
function SomeClass() {
if (!SomeClass.prototype.someMethod) {
SomeClass.prototype.someMethod = function() {}
}
}
This will slightly slow down the initial instantiation, though, as it is responsible for setting up the prototype - not really the job of an instantiation process.
There is also a programmatical difference to be aware of between your two cases:
function SomeClass(name) {}
SomeClass.prototype.someMethod = function() {};
var instance = new SomeClass();
console.log(!!instance.someMethod); //true
console.log(instance.hasOwnProperty('someMethod')); //false
The last line is false because the method is inherited, not owned by the instance. With your pattern B, this will resolve to true.
Correct: defining methods in the prototype will create 1 function object, and every instance will reference that 1 function. Defining it in the constructor creates a new function for each instance
Your code needs some work. The way you're defining the constructor, the doSomething function is defined as a global add var to counter that. This still doesn't set doSomething as a property though, it's just a function declared within the scope of the constructor (closure). This is why it doesn't show up in your instance as a method: the function is not attached to this, but even when fix this issue like so, you're still creating new function objects for each instance:
function MyConstructor()//capitalize constructors - conventions are important
{
var someMethod = function(){/*..*/};
this.someMethod = someMethod;
}
Utkanos pointed out what the implications of inheritance and prototype methods are (.hasOwnProperty), and he's absolutely right in that respect (+1). I'd just like to add that the hasOwnProperty method returning false is a trivial matter. Generally speaking, when iterating over an object, and checking which properties and methods are set, and which are not. What you want in most cases are properties, not the methods. So it's in fact better to set them at the prototype level:
for(var name in obj)
{
if (obj.hasOwnProperty(name))
{
//do stuff, here the methods are set # prototype level
}
if (obj.hasOwnPrototype(name) && typeof obj[name] !== 'function')
{
//same stuff, but requires extra check when methods are assigned by constructor
}
}

JavaScript Code Architecture - Use Constructor Functions Or Not

Please help me decide whether I should use a function's prototype object and the "new" keyword or completely stay away from constructor functions.
Situation:
Function called widget() that will be called 10-15 times to initialize each widget on the page. widget() contains quite a few internal methods.
Each time widget() is called, the function needs to return an object that acts as an API to operate on the widget.
Question
1) Do I put all the internal methods inside Widget() under its prototype property? It does not make sense but the main reason for this is to not re-instantiate the internal functions every time widget() is called.
But if I do put the internal functions in prototype, each instantiated w object (w = new Widget();) has access to internal private methods.
2) If I stay away from constructor functions and new keyword and structure my code as down below, how do I fix the performance concern of the internal functions getting re-instantiated every time widget() is called.
function widget()
{
var returnObj = {};
/* Add internal functions but this will be re-instantiated every time */
return returnObj;
}
You have a bit of a tradeoff here. As you seem to already understand, methods you put on the .prototype are publicly available, but that is the most efficient places to put methods as they are automatically added to all new copies of that object in a very efficient manner. When using .prototype for methods, there is only one copy of your methods and a reference to that single copy is automatically added to all new instantiations of that object.
But, javascript doesn't have private methods built-in and the only work-around for that involves not using the .prototype for them or for any methods that need to call the private methods.
This article by Doug Crockford is a pretty good description of how you can create privacy for either data or methods in any object.
In either case, I don't see any reason to avoid using the new keyword to create new objects. You can make either .prototype or private methods work with new.
But, if you want to achieve truly private methods, then you can't use .prototype for either the private methods or any methods that need to access them so you have to decide which is more important to you. There is no single correct answer because your need for privacy is situation-specific.
In my coding, I generally don't enforce privacy and I do use .prototype and new. I designate "non-public" methods on the prototype by starting their name with an underscore. This is a notational convention, not an access enforcement scheme.
In answer to your second question about avoiding the new operator and reinstantiating methods, I'd just ask why you're doing this? What are you gaining? I'm not aware of any downsides to using new. As best I understand your decision about whether to use .prototype vs. manually create/assign methods in your constructor should be about the need for private methods.
FYI, 15 objects is hardly going to create a significant difference in performance either way here. I would evaluate your need for true privacy and make your decision based on that. If you HAVE to enforce privacy, then go with the Crockford method for implementing private methods. If you don't HAVE to have true privacy, then use .prototype. I don't see a reason here to avoid using new in either case.
You can use a metaconstructor* pattern to get around this.
function defineCtor(metaCtor) {
var proto = new metaCtor();
var ctor = proto.hasOwnProperty('constructor') ?
proto.constructor : new Function();
return (ctor.prototype = proto).constructor = ctor;
}
Now you have a function that constructs constructors (or more accurately constructs prototypes and returns constructors).
var Widget = defineCtor(function() {
function doInternalStuff() {
// ...cant see me
}
// this function ends up on the prototype
this.getFoo = function() { return doInternalStuff(); };
});
// ...
var myWidget = new Widget();
Explanation
defineCtor takes a single anonymous function as a property. It invokes the function with new, creating an object. It assigns the object as the prototype property of a new constructor function (either an empty function, or the generated prototype object's own constructor property), and returns that function.
This provides a closure for your internal functions, addressing your question 1, and sets up the constructor/prototype pair for you, addressing question 2.
Comparison
Compare the defineCtor technique to the following two examples.
This example uses the prototype, and has problem 1: the internal stuff is not encapsulated.
function Widget(options) {
this.options = options;
}
Widget.prototype = {
getFoo: function() {
return doInternalStuff();
}
};
// How to encapsulate this?
function doInternalStuff() { /* ... */ }
This example sets up everything in a constructor, and has problem 2: each time it constructs an object, it instantiates new function objects for each property.
function Widget(options) {
this.options = options;
function doInternalStuff() { /* ... */ }
this.getFoo = function() {
return doInternalStuff();
};
}
This example uses the technique described above to provide encapsulation while still leveraging the prototype:
var Widget = defineCtor(function() {
// ^
// This function runs once, constructing the prototype.
// In here, `this` refers to the prototype.
// The real constructor.
this.constructor = function(options) {
// In function properties, `this` is an object instance
// with the outer `this` in its prototype chain.
this.options = options;
};
function doInternalStuff() { /* ... */ }
this.getFoo = function() { return doInternalStuff(); };
});
// ...
var myWidget = new Widget();
This approach has a few benefits, some more immediately obvious than others.
It provides encapsulation. You could do this by wrapping the first "comparison" example in an immediately invoked function, but this approach may be cleaner and more easily "enforced" in a team setting.
It's extensible. You can give your "metaconstructor" functions their own prototypes, with function properties like "extends", "mixin", etc. Then, inside the body of metaCtor, you can write things like this.extends(BaseWidget). The defineCtor API never needs to change for any of this to happen.
It "tricks" Google Closure Compiler, Eclipse, jsdoc, etc. into thinking you are defining the actual constructor function rather than a "meta function." This can be useful in certain situations (the code is "self-documented" in a way these tools understand).
* As far as I know, the word "metaconstructor" is completely made up.

Creating functions for an object in javascript

As far as I can tell, there are two main ways of creating functions for an object in javascript. They are:
Method A, make it in the constructor:
function MyObject() {
this.myFunc1 = function() {
...
}
this.myFunc2 = function() {
...
}
...
}
Method B, add it to the prototype:
function MyObject() {
...
}
MyObject.prototype.myFunc1 = function() {
...
}
MyObject.prototype.myFunc2 = function() {
....
}
Obviously if you did:
MyObject.myFunc3 = function() {
....
}
then myFunc3 would become associated with MyObject itself, and not any new objects created with the new keyword. For clarity, we'll call it method C, even though it doesn't work for creating new objects with the new keyword.
So, I would like to know what the differences between the two are. As far as I can tell they have the same effect logically, even if what's happening on the machine is different.
If I were to guess I would say that the only real difference is when you're defining them in the constructor like in method A, it creates a whole new function object for each object that's created, and Method B only keeps one copy of it (in MyObject), that it refers to any time it's called. if this is the case, why would you do it one way over the other. Otherwise, what is the difference between method A and method B.
The advantage of giving a separate function to each object is that you can close over variables in the constructor, essentially allowing for "private data".
function MyObject(a,b) {
var n = a + b; //private variable
this.myFunc1 = function() {
console.log(n);
}
};
vs
function MyObject(a,b) {
this.n = a + b; //public variable
}
MyObject.prototype.myFunc1 = function() {
console.log(this.n);
}
Whether this is a good idea or not depends on who you ask. My personal stance is reserving constructor functions for when I actually use the prototype, as in option #2 and using plain functions (say, make_my_object(a,b)) when using closures, as in option #1.
The idea is that you can modify the prototype at any time and all objects of the type (even those created before the modification) will inherit the changes. This is because, as you mentioned, the prototype is not copied with every new instance.
The MyObject in method A is an instance for inner functions.
You cannot call its functions explicitly outside of it unless object (you can call it a class) was instantiated.
Assume this:
MyObject.MyFunc1(); // will not work
var obj = new MyObject();
obj.MyFunc1(); // will work
so this is the same as any class in other languages. Describing usefulness of classes and their usages goes beyond that question though.
Also to notice:
function MyObject() {
var privateVar = "foo";
this.publicProperty = "bar";
// public function
this.publicFunc = function() {
...
}
// private function
function privateFunc () {
...
}
}
For method B it's same as with method A, the only difference is prototyping is a style of creating object. Some use prototypes for readability or out of preference.
The main advantage in prototypes is that you can extend existing object without touching the original source. You need to be careful with that though.
(as example Prototype framework)
For method C you can call them a static functions. As you said they can be called explicitly by referring through object like:
MyObject.MyFunc1();
So which one to use depends on situation you're handling.

Categories

Resources