I am just learning Javascript and I was wondering, is using the prototype declaration, like this:
function TSomeObj()
{
this.name="my object";
}
TSomeObj.prototype.showname = function() {
alert(this.name);
}
Basically the same as doing it like this:
function TSomeObj()
{
this.name="my object";
this.showname = function() {
alert(this.name);
}
}
When I dump the object’s properties I get the same result:
TSomeObj (inline version) =
{
'name': 'my object',
'test': function
}
TSomeObj (prototype declaration) =
{
'name': 'my object',
'test': function
}
What exactly is the benefit of using prototype declarations? Except less cluttering and more orderly sourcecode perhaps.
Update: I should perhaps have made it more clear that it was the final result i was curious about. The end result is ofcourse the same (i.e both register a new function in the object prototype) – but the way they do it is wildly different. Thank you for all replies and info!
Note: This answer is accurate but does not fully reflect the new way to create classes in JavaScript using the ES6
class Thing {}syntax. Everything here does in fact apply to ES6 classes, but might take some translation.I initially answered the wrong question. Here is the answer to your actually-asked question. I’ll leave my other notes in just in case they’re helpful to someone.
Adding properties to an object in the constructor function through
this.propis different from doing so outside throughObject.prototype.prop.The most important difference is that when you add a property to the prototype of a function and instantiate a new object from it, that property is accessed in the new object by stepping up the inheritance chain rather than it being directly on the object.
A second difference is that adding properties to a prototype occurs once when that code executes, but adding properties to the object inside the constructor occurs each time a new object is created. This means using the prototype performs better and uses less memory, because no new storage is required until you set that same property on the leaf/proximate object.
Another difference is that internally-added functions have access to private variables and functions (those declared in the constructor with
var,const, orlet), and prototype-based or externally-added functions do not, simply because they have the wrong scope:General notes about JavaScript objects, functions, and inheritance
All non-string and non-scalar variables in JavaScript are objects. (And some primitive types undergo boxing when a method is used on them such as
true.toString()or1.2.valueOf()). They all act somewhat like a hash/dictionary in that they have an unlimited(?) number of key/value pairs that can be assigned to them. The current list of primitives in JavaScript is: string, number, bigint, boolean, undefined, symbol, null.Each object has an inheritance chain of "prototypes" that go all the way up to the base object. When you access a property of an object, if that property doesn’t exist on the object itself, then the secret prototype of that object is checked, and if not present then that object’s prototype, so on and so forth all the way up. Some browsers expose this prototype through the property
__proto__. The more modern way to get the prototype of an object isObject.getPrototypeOf(obj). Regular objects don’t have aprototypeproperty because this property is for functions, to store the object that will be the prototype of any new objects created using that function as their constructor.A JavaScript function is a special case of an object, that in addition to having the key/value pairs of an object also has parameters and a series of statements that are executed in order.
Every time a function object is invoked it is paired with another object that is accessed from within the function by the keyword
this. Usually, thethisobject is the one that the function is a property of. For example,''.replace()boxes the string literal to aString, then inside the replace function, this refers to that object. another example is when a function is attached to a DOM element (perhaps an onclick function on a button), thenthisrefers to the DOM element. You can manually choose the pairedthisobject dynamically usingapplyorcall.When a JavaScript function is invoked with the
newkeyword as invar obj = new Obj(), this causes a special thing to happen. If you don’t specifically return anything, then instead ofobjnow containing the return value of theObjfunction, it contains the this object that was paired with the function at invocation time, which will be a new empty object with the first parent in its inheritance chain set toObj.prototype. The invokedObj()function, while running, can modify the properties of the new object. Then that object is returned.You don’t have to worry much about the keyword
constructor, just suffice it to say thatobj.constructorpoints to the Obj function (so you can find the thing that created it), but you’ll probably not need to use this for most things.Back to your question. To understand the difference between modifying the properties of an object from within the constructor and modifying its prototype, try this:
You’ll see that setting
a.prop1is actually creating a new property of the proximate object, but it doesn’t overwrite the base object’s prop1. When you removeprop1fromathen you get the inheritedprop1that we changed. Also, even though we addedprop2afterawas created,astill has that property. This is because javascript uses prototype inheritance rather than classic inheritance. When you modify the prototype ofTSomeObjyou also modify all its previously-instantiated objects because they are actively inheriting from it.When you instantiate a class in any programing language, the new object takes on the properties of its "constructor" class (which we usually think of as synonymous with the object). And in most programming languages, you can’t change the properties or methods of the class or the instantiated object, except by stopping your program and changing the class declaration.
Javascript, though, lets you modify the properties of objects and "classes" at run-time, and all instantiated objects of that type class are also modified unless they have their own properties that override the modification. Objects can beget objects which can beget objects, so this works in a chain all the way up to the base
Objectclass. I put "classes" in quotes because there really isn’t such a thing as a class in JavaScript (even in ES6, it’s mostly syntactic sugar), except that thenewkeyword lets you make new objects with the inheritance chain hooked up for you, so we call them classes even though they’re just the result of constructor functions being called with thenewkeyword.Some other notes: functions have a
Functionconstructor, objects have anObjectconstructor. The prototype of theFunctionconstructor is (surprise, surprise)Object.Inheriting from an object without the constructor function running
In some cases, it’s useful to be able to create a new "instance of an object" without the constructor function running. You can inherit from a class without running the class’s constructor function like so (almost like manually doing
child.__proto__ = parent):A better way to do this now is
Object.setPrototypeOf().