What is a difference between an object literal and a class with values in constructor in javascript? - javascript

I've been working on end to end test in testcafe and in their documentation I found following solution for Page Model:
class Page {
constructor () {
this.nameInput = Selector('#developer-name');
}
}
export default new Page();
I've been doing some research and I cannot get my head around why it is not resolved with an object literal:
export const Page = {
nameInput: Selector('#developer-name');
}
What are consequences of using each of them?

The difference is significant but fundamentally both are JavaScript objects, albeit with different properties and values. Listing all differences on the level of the language would be a long story and you'd be wise to read and understand on JavaScript prototype-based inheritance, but the most important differences are:
Page is a prototype object: whenever you create an object of class Page with new Page(), the constructor function is called with this referring to the object being created, not Page itself. Any property you access on the object is searched along the so-called "prototype chain", including the so-called prototype object. This prototype object can be accessed with Page.prototype and in fact, all methods you define in the class Page are also properties of this prototype object. Unlike own properties designed to refer to unique objects or primitives specific to an object, functions in JavaScript don't have to be bound to an object during object or function creation and can be shared between objects (belonging to the same class, for instance) and are called on the actual instance, not the prototype to which they may belong. In other words, this.nameInput in your constructor actually adds a property named nameInput to the object being created with new Page(), not the prototype, while the constructor itself (constructor) and any non-static methods you might add to Page will be added as properties of Page.prototype. The constructor is accessed as Page.prototype.constructor, by the way, as you'd naturally expect. Page.prototype.constructor === Page evaluates to true, by the way.
An expression of the form like { nameInput: ... } creates an object which prototype is Object.prototype, in practice the most basic form of object with "no prototype" and thus no superclass or any traits beyond what the fundamental object prototype object could provide. Any properties any such { ... } object may seem to have through its prototype chain, including methods, are properties of Object.prototype. This is why you can do ({}).toString() or ({}).hasOwnProperty("foobar") without actually having toString or hasOwnProperty properties in your object -- toString and hasOwnProperty are properties of Object.prototype referring to two distinct methods called toString and hasOwnProperty, respectively, and JavaScript creates a special property on your object called __proto__ referring to Object.prototype. This is how it knows how to "walk the prototype chain". The names of functions themselves do not matter like that, by the way -- I may add a property on an object referring to an anonymous function: var foo = ({}); foo.bar = function() { }; and call said unnamed function with foo.bar().
One mistake you appear to be making is confusing an object of a class with the class, otherwise you wouldn't compare export default class Page { ... } to export const Page = { nameInput: Selector(...) } -- the former creates a class accessible as Page which is used as the prototype object whenever objects of the class are created, while the latter creates an object accessible as Page which contains nameInput referring to result of evaluating expression Selector("#developer-name") (calling Selector with the sole argument "#developer-name"). Not the same thing at all, not to mention that former has Page refer to a class (invariably a prototype in JavaScript), while latter has Page refer to an object that does not seem to fit the pattern of a class.
The interesting things start when you realize that since a class is an object like any other in JavaScript, any object can be used as a class if you know how prototype-based inheritance works:
new (function() { this.nameInput = Selector("#developer-name"); })();
What happens here? You create a new object with an unnamed function as the object constructor. The effect is absolutely equivalent to otherwise creating the object with new Page with Page being your original ES6 class (ECMAScript 6 is the language specification that adds class syntax to JavaScript).
You can also do this, again equivalent to if you defined Page with class Page ...:
function Page() {
this.nameInput = Selector("#developer-name");
}
var foo = new Page();
Page.prototype will be the prototype object for foo, accessible as foo.__proto__ and otherwise making it possible for you to call instance methods on foo like foo.bar(), provided you define bar property on at least Page.prototype:
function Page() {
this.nameInput = Selector("#developer-name");
}
Page.prototype.bar = function() {
console.log(this.nameInput);
}
var foo = new Page();
foo.bar();
In fact, the above is what browser would do internally if it had to interpret the following code:
class Page {
constructor() {
this.nameInput = Selector("#developer-name");
}
bar() {
console.log(this.nameInput);
}
}
It is beyond the scope of my answer to list differences between the two last approaches (isn't the same thing as the two approaches you proposed), but one difference is that with class Page ..., Page is not a property of window in some user agents while with function Page ... it is. It's partly historical reasons, but rest assured that so far defining constructors and prototype using either approach is pretty much the same, although I can imagine smarter JavaScript runtimes will be able to optimize the latter form better (because it's an atomic declaration, and not just a sequence of expressions and statements).
If you understand prototype-based inheritance at the heart of all of this, all your questions about this will fall away by themselves as very few fundamental mechanisms of JavaScript support 99% of its idiosyncrasies. You'll also be able to optimize your object design and access patterns, knowing when to choose ES6 classes, when not to, when using object literals ({ prop: value, ... }) and when not to, and how to share fewer objects between properties.

Classes can be thought of as a blueprint, they both provide an object in the end. But as the object literals name implies, you literally create it there and then with this 'literal' syntax. A class however, we would use to instantiate new instances from 1 base blueprint.
let x = { myProp: undefined }
let y = { myProp: undefined }
x.myProp = "test";
y.myProp // undefined
Here we see we make two separate instances, but we will have to repeat code.
class X { }
let x = new X();
let y = new X();
A class does not need to repeat the code, as it is all encapsulated in the idea of what X should be, a blueprint.
Similar to above [in the literal] we have two separate instances but it's cleaner, more readable, and any change we wish to make to every instance of this 'X' object can now be changed simply in the class.
There's a plethora of other benefits and even a paradigm dedicated to Object-Oriented Programming, read here for more:
https://www.internalpointers.com/post/object-literals-vs-constructors-javascript
To go further into the constructor question... In other languages we have fields.
I believe when you assign a field in the constructor, it just creates an underthehood like field (I say underthehood like because JavaScript is prototype based, and the class syntax is syntactical sugar to help write prototypes easier for programmers familiar with class syntax in other languages).
Here is an example in C#.
public class X{
private int y;
X() {
this.y = 5;
}
}
It's more a convention to assign fields in the constructor in other languages, so I assume this has something to do with it in JavaScript.
Hope this helps.

By declaring it as a Class you can later identify what type of object it is with .constructor.name:
class Page {
constructor () {
this.nameInput = "something";
}
// No comma
anotherMethod() {
}
}
const pageClass = new Page();
const pageLiteral = {
nameInput: "something"
, // must have a comma
anotherMethod() {
}
}
console.log("Name of constructor for class: ", pageClass.constructor.name); // Page
console.log("Name of constructor for literal: ", pageLiteral.constructor.name); // Object

Related

Prototype property inside class constructor [duplicate]

I was trying ES6 syntax and find I cannot define prototype property or instance property within class defination, why forbids it?
I was using MyClass.prototype.prop=1 before, try ES7 by babel compiler as below, still cannot define prototype property.
class MyClass{
prop=1;
static sProp=1;
}
I don't think define instance property is any dangerous, there's 2 cases in my own browser game need prototype property:
Subclass instances need to inherit same property value from base class:
var Building=function(){...}
Building.prototype.sight=350;
TerranBuilding.CommandCenter=...(CommandCenter extends Building)
TerranBuilding.Barracks=...(Barracks extends Building)
So CommandCenter and Barracks will both have same building sight as 350.
new CommandCenter().sight===new Barracks().sight//All buildings have same sight
Buffer effect override original property and remove buffer
Marine.prototype.speed=20
var unit=new Marine()
unit.speed===20//get unit.__proto__.speed 20
unit.speed=5//Buffer:slow down speed, unit.speed will override unit.__proto__.speed
delete unit.speed//Remove buffer
unit.speed===20//true, speed restore
So I think it should add a way to set prototype property instead of forbid it completely, or can you give some other solutions to deal with above 2 cases?
Updated Answer (April, 2022)
Just two months after my previous answer, in August of 2021, the static block proposal was moved to stage 4 by the TC-39 committee. See the whole informal list of finished proposals here.
For those looking to get a use case summary of static blocks in Javascript, read the initial publication from the V8 blog from March 2021, after their implementation.
Also, see the MDN documentation for static initialization blocks.
Though most all updated browsers now support this, read below if you really like to support Internet Explorer.
Original Answer
Below is the typical pattern I follow in javascript. Native, no babel, etc..
It mirrors the static-block style that java uses. There is a Stage 3 Proposal open for this right now, and I expect therefor, that it will be standardized in the near future (as is consistent with the stage 3 proposal expectations of the TC-39 committee).
What the proposal will look like
class MyClass {
static {
// Any code here is executed directly after the initialization
// of MyClass. You can add prototype stuff here. The function
// is called bound to `MyClass`.
}
}
This can be done today using a static iife
These will function exactly the same way.
class MyClass {
// Using private properties is not required, it is just an option. Make
// sure to use an arrow function so that `this` refers to `MyClass`,
// Note that `MyClass` will still be in the functions closure.
static #_ = (() => {
// 'Almost' how functions are typically added. ES6 style
// is always recommended over this.
this.prototype.myFunc = function myFunc() {
console.log(":D");
};
// ES6 would actually do this (approximately) so that the function is
// non-enumerable in the prototype.
Reflect.defineProperty(this.prototype, "myFunc", {
// enumerable: false, // defaults 'false'
writable: true,
configurable: true,
// I'm intentionally not using the shorthand for the function
// so that it is named 'myFunc'.
value: function myFunc() {
console.log(":D");
}
});
// Note that all children of MyClass will refer to this exact
// object if put in the prototype, i.e. not a copy of it.
// Also, this property will be non-enumerable on the children
// (but enumerable on the prototype itself unless you
// use `defineProperty` as above).
this.prototype.sharedProperty = { name: "Gerald" };
})();
}
Neither of those will be on the class prototype.
The class Foo { bar = 1; } syntax will assign a value to the class instance, to be accessed with this.bar.
The class Foo { static bar = 1; } syntax will assign a value to the class constructor, to be accessed with Foo.bar.
There isn't much reason to use the prototype in this case. It will only complicate who actually owns the property and assigning a number in a few different classes will have very little overhead.
I would suggest the class instance property and just use this.sight everywhere you need it.
The simplest way to add a property to the prototype inside the class body is by using the prototype assignment as a "value" for a dummy static property:
class MyClass {
static _dummy = MyClass.prototype.prop1 = <expression1>
static _dummy = MyClass.prototype.prop2 = <expression2>
// or
static _dummy = this.prototype.prop2 = <expression2>
}
(it works without parentheses because = is right-associative, and it's fine to re-use the same dummy property for each prototype assignment)
If you want to do more interesting (multi-line) computation for the values, an initializer can be an immediately-executed function expression, in which case you've basically created a static constructor and you can put all the initializations for the prototype and class object in that.
I think the other answer didn't get the point of this question. The whole point of having inheritance is that you can decide when and where to override something. and if anyone think that's an overhead, why does ya use an OOP language at all?
I don't know why it's "forbidden" after all, but I could share some ideas.
I'm pretty sure there is no way to define a Prototype Property with 'class' keyword. Any definition will be install on "hasOwnProperty". A huge setback is that in a constructor, there is no way to have any parents' constructors to interact with an overridden property.
To the point of reasoning, it's actually expelled by an other feature: you can use expressions to assign properties to this.
class A extends B { sight = this.getSight() * 3 }
When an expression excuses, it is either run with instance - created with constructor, or run at class declaration - when the prototype is created.
Accessors and methods don't have this problem. They are defined at prototype definition time and called at instance run time.
Property defined with expression with "=" is the return value of the expression. It is excused right after definition - should be the instance creation time, otherwise this could not be available.
So it's nothing about patterns. It's about having expressions or having inheritance. I definitely prefer inheritance, expressions are so pointless when you can write them right into the constructor.
class A extends B { constructor() { this.sight = this.getSight() * 3 }
Using decorators are a nice work around. You can always do something with the prototype in javascript:
#B({sight:2}) class A {};
decorator B is:
function(option) {return function(clazz) {clazz.prototype.sight = option.sight; return clazz}}
Using Class static initialization blocks1:
class MyClass {
static {
this.prototype.prop = 1;
}
}
console.log(MyClass.prototype.prop); // 1
const instance = new MyClass();
console.log(instance.__proto__.prop); // 1
this in the static block differs as1:
The this inside a static block refers to the constructor object of the class.
The code inside the static block is executed only once when the class initialization gets evaluated.
Note: Safari doesn't support this feature as of June 2022. You can check the latest info on, for example, mdn web docs1.
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_static_initialization_blocks
class MyClass {
constructor() {
MyClass.prototype.prop2 = "Marry";
}
}
const mc = new MyClass()
mc.__proto__ // { prop2: "Marry" }

Making Sense of Class Keyword in Javascript

I am getting into ES6 lately and finally looking into classes seriously. I read that classes are just a cover over Objects in Javascript, however, I am finding the syntax most uncomfortable.
Could someone please explain / point to a reference where they explain, how classes simulate & importantly how we can map them into Javascript way of Object manipulation in our mind.
class NoteStore {
constructor() {
this.bindActions(NoteActions);
this.notes = [];
}
}
As per the example code above, I thought classes are mere constructors, but then what is a constructor doing within a constructor?
As someone who started learning programming with Js, I find the addition of classes (also React's classes) to be a terrible addition to Js so any help would be awesome.
Thanks
Classical class-based programming is based on defining a class which contains a constructor method and other methods which will be inherited by the constructed object. This is written as you show in your sample: the class is defined with its name, then contains a constructor function, then further functions.
The constructor method in a class definition is somewhat special, in that it gets invoked upon object construction. Since it's special, it somehow needs to be marked as such, and that's done by naming it constructor.
In classical Javascript (prototype-based OOP), this works differently: an object constructor is a simple function, and methods inherited by each object instance are defined on an object on the .prototype property of that function. There's nothing special about the constructor in prototype-based OOP, it's just a function, and the real magic lies in the new keyword and the use of this when the object gets constructed.
Expressing this in the form of a class with a constructor method is merely catering to classical-OOP developers, and arguably provides a more compact syntax.
class NoteStore {
constructor() {
this.bindActions(NoteActions);
this.notes = [];
}
bindActions(actions) {
..
}
}
This expressed in simple Javascript is:
function NoteStore() {
this.bindActions(NoteActions);
this.notes = [];
}
NoteStore.prototype.bindActions = function (actions) {
..
}
I think the explanation at MDN is quite clear.
class keyword is nothing but a new name for old style OOP implementation where we use a function constructor to get same functionality.
class keyword is brought to JavaScript to make it more similar to other traditional object oriented languages like C++, Java. But at core it is still function constructor with few changes.
For your question "what a constructor doing under constructor" ES6 has done some modification for older version so that class will not act as a constructor for examaple class cannot be invoked directly(without new keyword) like
NoteStore();
This will throw error in ES6 but if it was a function constructor like in ES5 than it works leaving you in a risk of bugs. classes are also not Hoisted.
For more detail and example you can read this link.
The JS class keyword:
Javascript has a system of inheritance which is called prototypal inheritance. This is a system were objects inherit properties from other objects. When a function is invoked using the new keyword the new object created with it 'inherits' properties from from the constructor function's prototype property.
The JS class keyword is merely syntactical sugar for a constructor function. The class keyword just has different syntax but it essentially achieves the same goal of Object creation with prototypes. Take for example the following snippet:
class human {
constructor (name) {
this.name = name;
}
speak () { console.log('hi')}
};
console.log(typeof human);
// logs function, a class is just a constructor function under the hood
const me = new human('Willem');
console.log(Object.getPrototypeOf(me) === human.prototype);
// logs true, the object me has a reference to the human.prototype object.
me.speak();
// This speak method is located on the prototype of the object, not the object itself
console.log(me.hasOwnProperty('speak')); // logs false
console.log(human.prototype.hasOwnProperty('speak')); // logs true

If Javascript's native OOP is classless, what about the constructor? Doesn't that imply a class?

I think Javascript native OOP system is said to be classless, and is object-based, not class-based. But every example I see always start with a constructor similar to
function Person(name) {
this.name = name;
}
Just by using a constructor this way, doesn't this already imply a class is being used? (a class called Person)
Details:
If we can use
a.__proto__ = b;
on any Javascript platform, then I think it is classless. But we can't do that. If we want that behavior, we need to use
function F() { }
F.prototype = b;
a = new F();
and so, a constructor has to be used. So if constructor is such a cornerstone in Javascript, that means it is intended to be constructor of Person, Widget, etc, and these are classes.
The OOP in Javascript is slightly different from, for instance, the Java OOP.
The Javascript constructors do not refer to a class definition (so it is classless). Rather the constructor refers to a prototype. The base of the OOP in Javascript is the Object object (not the Object class), from where all the others objects are derived.
Prototyping grants you inheritance, and the possibility to extend an existing object with properties and methods.
I suggest you this article.
In your example:
function Person(name) {
this.name = name;
}
Mike = new Person('Mike');
the Person() function lets you create a new object prototyped on the Object object with a new property called name. Well, such a kind of function in Javascript oop is called a constructor.
Classless may be an inaccurate way to describe JavaScript's approach on OOP.
JavaScript does lack class definitions.
It also lacks a class-to-object correspondence.
You can't check if an object instantiated with a constructor such as Person is of class Person.
You can check if it contains the expected object members and conclude that it is of the expected class.
But if the object members have been changed along the way you're not going to get the desired/expected result.
TL;DR
JavaScript exposes constructors (appropriately named prototypes) as a manner in which you can define a template for constructing plain objects.
The important thing is that the end result of a prototype call is a plain object with some predefined members and not an object of a certain class .
It's good to think of javascript as a classless environment. If you think javascript classes you should be able to assume there's certain useful things you can do when there are classes and they're strictly enforced. However those certain useful things you cannot assume. The presence of something that looks like a constructor does not indicate you're creating a class.
For example, let's say you var dude = Person('Ashton Kutcher'). Now, when you dude instanceOf person, you get true. You assume you have the properties and methods of a person. What if some code comes along and says dude.personMethod = undefined. Now, while dude instanceOf person will still be true, the personMethod is no longer available.
You can think of javascript as having classes but it's a leaky abstraction. It's better to think of javascript as having a prototypal inheritance system when it comes to determining what something is and what you can expect of it.
More information here: http://javascript.crockford.com/prototypal.html
Create a class using the Object Constructor and prototyping can help us
in creating many instances of the class without redefining the object each time wee need it.
so in the above example
function Person(name)
{
this.name = name;
}
you can create two persons with different names.
example :
var personA = new Person();
personA.name = "james";
var personB = new Person();
personB.name = "Tom";
alert(personA.name + personB.name);
i suggest you reading this link will be helpful
http://www.javascriptkit.com/javatutors/oopjs2.shtml

Is there any benefit to using prototype instead of declaring properties on the object itself?

A prototype is used to declare properties and methods for a class of objects. One advantage of using prototype is that it conserves memory because all instances of a class point to the properties and methods of the prototype which conserves memory and effectively allows properties to be treated as static by all instances of a class.
Prototype is used for inheritance through prototype chaining.
My question is very simple. Why use prototype at all when you can just do:
function car() {
this.engine = "v8";
}
function mustang() {
// nm, no good way to inherit without using prototypes
}
Is that right? So the primary purpose of prototypes is threefold:
conserve memory
provide static properties
is the only way for a reference type to inherit from a super class
conserve memory
Yes it does, when you create hundreds of instances of Car and they all have their own functions (that have their own closure scopes) you'll consume more memory.
Can't find a reference for it but it has been suggested that Chrome optimises constructor functions that use prototype better than constructor functions with everything in the constructor body.
provide static properties
Static is more like Date.now(), every instance has members from the prototype but can be called on the instance.
is the only way for a reference type to inherit from a super class
You can inherit with Parent.apply(this,arguments); in Child but it makes extending Parent functions more complicated and doesn't make childInstance instanceof Parent true. What that code does is run Parent code with the to be created Child instance as the invoking object (this). Inheritance is usually done in 2 places.
In the Child body Parent.apply(this,arguments); to re use Parent initialisation code and make Parent instance members to be Child instance members (for example: this.name).
Setting Child.prototype to shallow copy of Parent.prototype Child.prototype=Object.create(Parent.prototype);Child.prototype.constructor=Child; This will ensure that shared Parent members are available on Child instances (like the function getName).
These points are explained in more detail here: https://stackoverflow.com/a/16063711/1641941
Concerning your three points:
Prototypes aren't necessarily more performant, especially for prototype chains that become long or contain many members. The smaller the prototype and shorter the chain, the more the browser's compiler can optimize it. Ultimately, this question needs to be asked for individual applications, their individual needs, and the browsers being targeted (which can vary widely in performance).
By definition, static members require objects. That is, static members belong to an object itself rather than to a specific instance. Objects are the only way to create static properties in JavaScript. Note that object literals, which are a "special" kind of Object, are essentially static.
One could implement his own type of object that would allow for something like inheritance (i.e., jQuery.extend), but as far as reference types go, prototypes are the only way to create inheritance.
Prototyping is a lot more than that.
You can also extend classes and already existing instances of objects with methods and properties during runtime.
This should explain it in a very understandable way: http://javascript.info/tutorial/inheritance
If you care about following conventions so that people (and you down the road) actually understand your code, you shouldn't put this.engine="v8" in the constructor. Prototype is meant to define properties for every single car, and the constructor is meant to define individual instances. So why would you put something that is true for every instance smack dab in the constructor? This belongs in the prototype. There's something to be said for putting things in their proper place even if doing both things end up doing accomplishing the same thing. Your code will be understandable by you and others.
Regarding your points:
There is definitely a performance boost, especially regarding functions - it's much better to declare functions on the prototype.
I think you meant to say "public" properties so that information is retrieved by writing some_instance.foo. "Static" properties/methods are different (see below).
Correct. Inheritance can only really happen from the prototype.
Let me explain some things to see if this helps. Creating new "classes" in javascript is a fairly straightforward process.
var MyClass = new Function();
At this point, the engine is aware of your new class and knows "what to do" (in terms of performance) when it creates new instances of your "class".
var my_instance = new MyClass();
If you want to modify the prototype, you can do so and know that every instance is going to get updated because they all share the same prototype.
MyClass.prototype.name = "default name";
console.log( my_instance.name ); //=> default name
Now the engine knows that there is a "name" property which expects a string value... it will allot those resources to all new AND existing instances of your class... which is very handy. Beware that modifying the prototype of an existing "class" like this is an expensive process and should not be performed frequently (but don't be afraid to do it either).
I can't really speak for the performance pros and cons of declaring ad-hoc properties/methods on an instance:
my_instance.foo = function() { /* this is not in the prototype chain */ };
My guess is that this is pretty simple for the engine and is no big deal unless you are doing this for tens of thousands of objects at the same time.
The main benefit of using the prototype IMO is that you can write code to extend a method's functionality and know that all instances of your "class" will get updated accordingly:
var old_foo = MyClass.prototype.foo;
MyClass.prototype.foo = function() {
/* new business logic here */
// now call the original method.
old_foo.apply(this, arguments);
};
Regarding "static" properties, you declare those on the "class" (constructor) itself:
// example static property
MyClass.num_instances = 0;
Now you can create init/destroy methods like this:
MyClass.prototype.init = function() {
this.constructor.num_instances++;
};
MyClass.prototype.destroy = function() {
this.constructor.num_instances--;
};
// and call the init method any time you create a new instance
my_instance.init();
console.log( MyClass.num_instances ); //=> 1
var instance_2 = new MyClass();
instance_2.init();
console.log( MyClass.num_instances ); //=> 2
instance_2.destroy();
console.log( MyClass.num_instances ); //=> 1
Hope that helps.
(1) I don't think conserving memory alone is a valid reason to utilize .prototype, unless you're getting really extreme with duplicating objects.
(2) The idea of static properties is not really a reason to use .prototype either (IMHO), because it doesn't behave like a traditional static property. You (as far as I know) always need an object instance before you can access the "static" property, which makes it not static at all.
function Car() {}
Car.prototype.Engine = "V8";
// I can't access Car.Engine... I'll always need an instance.
alert(new Car().Engine);
// or
var car1 = new Car();
alert(car1.Engine); //you always need an instance.
//unless you wanted to do
alert(Car.prototype.Engine); //this is more like a static property, but has an
//unintended consequence that every instance of Car also receives a .Engine
//behavior, so don't do this just to create a "static property."
It should be noted that this "static" idea not only applies to properties but all members, which includes methods (functions), from a traditional OO perspective.
It is better to think about prototypes (again, IMHO) as injected singleton objects with behaviors that get attached to instance objects. All instances of Car() can have their own instance members, but every instance of Car() will also "automatically" be injected with all Car.prototype's members/behaviors. It's not technically the same, but I find it convenient to think about prototypes in that way.
//define Car and Car.GoFast
function Car() {}
Car.prototype.GoFast = function () { alert('vroom!'); };
var car1 = new Car();
var car2 = new Car();
car1.GoFast();
car2.GoFast(); //both call to same GoFast implementation on Car.prototype
//change the GoFast implementation
Car.prototype.GoFast = function () { alert('vvvvvrrrrroooooooooommmmm!!!!!'); };
car1.GoFast();
car2.GoFast(); //both have been "updated" with the new implementation because
//both car1 and car2 are pointing to the same (singleton) Car.prototype object!
Car.prototype is behaving like a singleton object whose members/behaviors have been injected into instance objects of type Car.
(3) Prototypes shouldn't be confused for inheritance. You can get behavior that appears to be inheritance, but it is not. The members/behaviors on the prototype remain on the prototype object. They do not become members/behaviors of your derived class, like true inheritance. That is why I describe it more like the prototype being "injected" into your instance.
function Car() {}
Car.prototype.Engine = "V8";
var car1 = new Car();
var car2 = new Car();
alert(car1.Engine); //alerts "V8"
//There is no "Engine" variable defined within the instance scope of 'car1'.
//Javascript searches the scope of car1's Type.prototype object to find 'Engine'.
//Equivalent to: Object.getPrototypeOf(car1).Engine
//But if we create 'Engine' within the scope of car1
car1.Engine = "V6"; //Car.prototype was never accessed or updated
alert(car1.Engine); //we get "V6"
alert(car2.Engine); //we still get "V8"
alert(Object.getPrototypeOf(car1).Engine); //we still get "V8"!
So to answer the question directly: Is there any benefit to using prototype instead of declaring properties on the object itself?
Yes, when you want to share behavior implementation amongst instance objects of a given Type. As a coincidence, you will reduce your memory footprint, but that is not a reason alone to use prototypes. Neither is "creating static properties" (which they're not ), or for inheritance (which it is not).

javascript inheritance

I know there is a lot of similar questions are tons of great answers to this. I tried to look at the classical inheritance methods, or those closure methods etc. Somehow I consider they are more or less "hack" methods to me, as it doesn't really what the javascript is designed to do. (Welcome anybody correct me if I am wrong).
OK, as long as it works, I satisfy with the classical inheritance pattern like:
PARENTClass = function (basevar) { do something here; };
PARENTClass.prototype = { a: b, c: d}; // prototype is auto gen
// Inheritance goes here
CHILDClass = function (childvar) { do something; };
CHILDClass.prototype = new PARENTClass(*1); // Actual inheritance to the prototype statement
// Instance
CHILDInstance = new CHILDClass(whatever);
Above is somehow, to my understanding the inheritance of JS. But one scenario I have no idea how to implement, is that what if I want to do some initializing DURING object creation (ie, within constructor), and the new object can be used right away.... My illustration on problem might not be too clear, so let me use the following C# Psuedo to explain what I want to do:
class PARENT {
public PARENT (basevar) { ... }
}
class CHILD : PARENT {
public CHILD (basevar) : PARENT (basevar) // constructor of child, and call parent constructor during construct.
{ ... }
}
For some reason (like init. UI elements), putting them in constructor seems the best way to do. Anyone have idea on how can I do it.
PS: in the *1, I have no idea what I should put there.
PS2: The above situation I DID found the jquery.inherit library can do, I just wonder if not using library can achieve it.
PS3: Or my understanding is wrong. Since javascript is not intended to mimick OOP (that's why i call it hack), what is the "CORRECT" logic to implement this.
It is not a hack as such; JavaScript is a prototyped language, as defined by Wikipedia as where:
..classes are not present, and behavior reuse (known as inheritance in class-based languages) is performed via a process of cloning existing objects that serve as prototypes.
As it says, classes are not used in JavaScript; each object that you create is descended from the JavaScript Object; all objects in JavaScript have the prototype object, and all instances of objects you create 'inherit' methods and properties from their object's prototype object. Take a look at the MDC prototype object reference for more information.
As of this, when you call the line:
CHILDClass.prototype = new PARENTClass();
This allows the CHILDClass object to add methods and properties to its prototype object from the PARENTClass object, which creates an effect similar to the idea of inheritance present in class-based languages. Since the prototype object affects every instance created of that object, this allows the parent object's methods and properties to be present in every instance of your child object.
If you want to call your parent class's constructor in your child class's constructor, you use the JavaScript call function; this allows you to call the parent class's constructor in the context of the child class's constructor, therefore setting the newly prototyped properties in your child class to what they are set as in the parent class.
You also do not need to put anything where you have specified the *1, since that line is merely used to add the methods and properties to the child class's prototype object; however, bear in mind that it calls the parent class's constructor, so if there are any arguments that are fundamental in the operation of the parent class constructor, you should check that these are present so as to avoid JavaScript errors.
You can manually invoke the parent constructor in the subclass constructor like this:
CHILDClass = function (basevar) {
PARENTClass.call(this, basevar);
// do something;
};
The trick here is using the call method, which allows you to invoke a method in the context of a different object. See the documentation of call for more details.
JavaScript has no built-in support for inheritance hierarchies as type extension is supposed to be done via aggregation, ie adding desired functionality directly to the object itself or its prototype if the property is to be shared between instances.
Nevertheless, JS is powerful enough to make implementing other forms of object construction possible, including classical inheritance.
Given a clone function - which is enough to add 'true' prototypical inheritance, and not JavaScript's bastardization thereof - your exampe can be implemented like this:
function ParentClass(baseVar) {
// do stuff
}
// don't overwrite the prototype object if you want to keep `constructor`
// see http://joost.zeekat.nl/constructors-considered-mildly-confusing.html
ParentClass.prototype.a = 'b';
ParentClass.prototype.c = 'd';
function ChildClass(childVar) {
// call the super constructor
ParentClass.call(this, childVar);
}
// don't inherit from a ParentClass instance, but the actual prototype
ChildClass.prototype = clone(ParentClass.prototype);
ChildClass.prototype.e = 'f';
It's also possible to add some syntactic sugar for class-based inheritance - my own implementation can be found here.
The example from above would then read
var ParentClass = Class.extend({
constructor: function(baseVar) {
// do stuff
},
a: 'b',
c: 'd'
});
var ChildClass = ParentClass.extend({
e: 'f'
});
I've got a lightweight javascript OOP wrapper that provides 'Class-like' inheritance where you can override base methods or call base constructors or members.
You define your classes like this:
//Define the 'Cat' class
function Cat(catType, firstName, lastName)
{
//Call the 'Animal' constructor.
Cat.$baseNew.call(this, firstName, lastName);
this.catType = catType;
}
//Extend Animal, and Register the 'Cat' type.
Cat.extend(Animal, { type: 'Cat' }, {
hello: function(text)
{
return "meaoow: " + text;
},
getFullName: function()
{
//Call the base 'Animal' getFullName method.
return this.catType + ": " + Cat.$base.getFullName.call(this);
}
})
//It has a built-in type system that lets you do stuff like:
var cat = new Cat("ginger", "kitty", "kat");
Cat.getType() // "Cat"
cat.getBaseTypesAndSelf() // ["Cat","Animal","Class"]
cat.getType() // "Cat"
cat.isTypeOf(Animal.getType()) // "True"
var dynamicCat = Class.createNew("Cat", ["tab","fat","cat"])
dynamicCat.getBaseTypesAndSelf() // ["Cat","Animal","Class"]
dynamicCat.getFullName() // tab: fat cat
source code available at: Class.js
I also have more details in my blog post about OOP in javascript
Just thought I'd mention some of the issues with the classical pattern you're going for:
Reference vars on the super class(es) will be available as essentially statics on ALL instances. For example, if you have var arr = [1,2,3] in the super, and do instance_1.arr.push(4) instance_2.arr.push(5) ALL of these instances will "see" the changes.
So you solve 1. with Ayman's solution which Zakas calls "Constructor Stealing", but now you call the constructor twice: once for your prototype and once for the constructor stealing. Solution - for your prototype use a helper like inheritPrototype (I showed the whole implementation of this in this post: inheritPrototype method FWIW, this essentially came from a combination of page 181 of Zakas's book and some Crockford study.
No privacy (but then again, you'd need to use something like the Durable Object pattern to get this and that may not be what you want)
Object definition is left "dangling": Solution - put an if statement checking for any of your prototype's functions and then define the prototype with a prototype literal.
I have running examples of all of this on github!!!
It's been just as much of a challenge for me to truly grok both: Zakas and Crockford books on object creation and inheritance. I also needed to try some different JavaScript TDD frameworks. So I decided to create an essay on both TDD Frameworks and JavaScript Object Creation & Inheritance. It has running code and jspec tests! Here's the link:*
My GitHub Open Source Essay/Book

Categories

Resources