This link states we can create a constructor using a constructor method.
I wanted to know when would I use that and how is it different from constructor functions. From what I understand is. A regular function is a constructor function when its called with new. What role does "constructor" keyword play in this example
class Cat {
constructor(name,color){
this.name = name;
this.color = color;
}
speak(){
console.log("Meow");
}
}
When instantiating a new instance of this class with new Cat(), you'd pass in the name and color of the cat in the order defined by the constructor arguments. You'll then have a new instance of Cat with the name and color properties defined.
const spot = new Cat('Spot', 'Orange')
That will create a new cat with a name of "Spot" and a color of "Orange". It's just a reserved keyword that is executed when a new instance is created.
It's similar to the ES5 syntax, just with some syntactic sugar:
function Cat(name, color) {
this.name = name;
this.color = color
}
Cat.prototype.speak = function() {
console.log('Meow')
}
const c = new Cat('Spot', 'Orange')
c.speak() // Meow
console.log(c.name, c.color) // Spot Orange
You can read more on MDN
Do not forget that there's no real class in javascript. If you try to transpile your class, you will get something similar to:
var Cat = function () {
function Cat(name, color) {
this.name = name;
this.color = color;
}
Cat.prototype.speak = function speak() {
console.log("Meow");
};
return Cat;
}();
No surprise, the constructor is a constructor function.
The constructor method within a class declaration/expression is required as part of the syntax. It supplies the code to execute when "creating" a new instance of the class. Here "creating" and "constructing" mean the same thing in JavaScript.
The constructor method of the class creates a constructor function object that is the value of the class declaration:
class myClass {
constructor() {
this.bar = "foo";
}
moreInfo() {
console.log( "myClass is the same as its constructor method = "
+ (myClass === this.constructor));
}
}
// what is myClass?
console.log( new myClass().moreInfo());
So, long story short, class declarations create a constructor function of the same name.
Going back to basic JS, all standard functions (that are not either arrow
functions or class declarations or expressions) can be used as constructor functions by design: just because you never use them as a consctructor doesn't mean you couldn't. Of course, the sense of using a particular function as a constructor does depend on whether it was written for the purpose of constructing objects:
function add( a, b) { // Not written as a constructor
return a+b;
}
function record( a, b) { // written as a constructor
this.a = a;
this.b = b
}
Every object prototype in JavaScript comes with a constructor method. The constructor method is the constructor function used to create the object.
For instance, we can turn a number into a string using the String constructor
String(2) === "2";
we can also do
"".constructor(2) === "2"
This works the same because the string's "constructor" points to the String constructor function.
Classes in JavaScript aren't classes as they exist in languages like Java or Ruby since JavaScript uses a prototypal inheritance system. So classes in JavaScript are just sugar syntax for plain constructor functions. This allows developers to take advantage of some OOP features of JavaScript without needing to know about many of the nuances about how its inheritance system works.
So the following:
function Cat (name,color){
this.name = name;
this.color = color;
}
Cat.prototype.speak = function(){
console.log("Meow");
}
Is effectively the same as
class Cat {
constructor(name,color){
this.name = name;
this.color = color;
}
speak(){
console.log("Meow");
}
}
Both can be instantiated using the new keyword
new Cat("Mittens", "black");
The "constructor" as described in the class example points to the underlying JavaScript constructor function. Remember that "class" in JavaScript is just a friendly wrapper around a constructor function that makes using it more similar to using classes in other languages.
When working with a class you'd use the "constructor" method to set some values directly to the object that will be created, rather than on its prototype. The prototype is an object common to all objects created with a class/constructor, that's used to share functionality between them.
Related
I'm on "Introducing ES2015" course of Treehouse and the teacher shows this code to illustrate the arrow functions but here he instantiates the function as a class. Can anybody tell me how is it possible?
What I learned about objects is that you need to create a class before to instantiate it or create a literal object which is not this case.
'use strict';
var Person = function(data) {
for (var key in data) {
this[key] = data[key];
}
this.getKeys = () => {
return Object.keys(this);
}
}
var Alena = new Person({ name: 'Alena', role: 'Teacher' });
console.log('Alena\s Keys: ', Alena.getKeys()); // 'this' refers to 'Alena'
var getKeys = Alena.getKeys;
console.log(getKeys());
Everything works but I don't know why.
You should ask yourself one question: What is a class really?
Actually it is just a syntax to compose the following things:
1) A constructor. That is some kind of function, that constructs an instance of the class.
2) methods. They can be called on instances.
Now for the second one, JS has already a great feature to achieve this: Prototypal Inheritance. Objects can inherit other objects, including methods:
const proto = { method() { /*...*/ } };
const instance = Object.create(proto);
instance.method(); // that works, as instance inherits proto
Now we only need constructors, for that we could just call a function after we created an object using the method above:
constructInstance(Object.create(proto));
Now as that is quite a common task (as JS has prototypal inheritance from the beginning), the new operator was added, which basically does all that:
1) It creates an empty object inheriting from .prototype of the function called on.
2) It calls the function itself with this being the object.
3) It gives back that object.
function Person(name) {
this.name = name;
}
Person.prototype.method = function() { /*...*/ };
new Person("Jonas").method();
And there you go, inheritance & constructors without any classes.
Now as that is still no quite beautiful, the class syntax was added, which basically just creates a function with a prototype.
So far I saw three ways for creating an object in JavaScript. Which way is best for creating an object and why?
I also saw that in all of these examples the keyword var is not used before a property — why? Is it not necessary to declare var before the name of a property as it mentioned that properties are variables?
In the second and third way, the name of the object is in upper-case whereas in the first way the name of the object is in lower-case. What case should we use for an object name?
First way:
function person(fname, lname, age, eyecolor){
this.firstname = fname;
this.lastname = lname;
this.age = age;
this.eyecolor = eyecolor;
}
myFather = new person("John", "Doe", 50, "blue");
document.write(myFather.firstname + " is " + myFather.age + " years old.");
Second way:
var Robot = {
metal: "Titanium",
killAllHumans: function(){
alert("Exterminate!");
}
};
Robot.killAllHumans();
Third way — JavaScript objects using array syntax:
var NewObject = {};
NewObject['property1'] = value;
NewObject['property2'] = value;
NewObject['method'] = function(){ /* function code here */ }
There is no best way, it depends on your use case.
Use way 1 if you want to create several similar objects. In your example, Person (you should start the name with a capital letter) is called the constructor function. This is similar to classes in other OO languages.
Use way 2 if you only need one object of a kind (like a singleton). If you want this object to inherit from another one, then you have to use a constructor function though.
Use way 3 if you want to initialize properties of the object depending on other properties of it or if you have dynamic property names.
Update: As requested examples for the third way.
Dependent properties:
The following does not work as this does not refer to book. There is no way to initialize a property with values of other properties in a object literal:
var book = {
price: somePrice * discount,
pages: 500,
pricePerPage: this.price / this.pages
};
instead, you could do:
var book = {
price: somePrice * discount,
pages: 500
};
book.pricePerPage = book.price / book.pages;
// or book['pricePerPage'] = book.price / book.pages;
Dynamic property names:
If the property name is stored in some variable or created through some expression, then you have to use bracket notation:
var name = 'propertyName';
// the property will be `name`, not `propertyName`
var obj = {
name: 42
};
// same here
obj.name = 42;
// this works, it will set `propertyName`
obj[name] = 42;
There is various way to define a function. It is totally based upon your requirement. Below are the few styles :-
Object Constructor
Literal constructor
Function Based
Protoype Based
Function and Prototype Based
Singleton Based
Examples:
Object constructor
var person = new Object();
person.name = "Anand",
person.getName = function(){
return this.name ;
};
Literal constructor
var person = {
name : "Anand",
getName : function (){
return this.name
}
}
function Constructor
function Person(name){
this.name = name
this.getName = function(){
return this.name
}
}
Prototype
function Person(){};
Person.prototype.name = "Anand";
Function/Prototype combination
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
return this.name
}
Singleton
var person = new function(){
this.name = "Anand"
}
You can try it on console, if you have any confusion.
There is no "best way" to create an object. Each way has benefits depending on your use case.
The constructor pattern (a function paired with the new operator to invoke it) provides the possibility of using prototypal inheritance, whereas the other ways don't. So if you want prototypal inheritance, then a constructor function is a fine way to go.
However, if you want prototypal inheritance, you may as well use Object.create, which makes the inheritance more obvious.
Creating an object literal (ex: var obj = {foo: "bar"};) works great if you happen to have all the properties you wish to set on hand at creation time.
For setting properties later, the NewObject.property1 syntax is generally preferable to NewObject['property1'] if you know the property name. But the latter is useful when you don't actually have the property's name ahead of time (ex: NewObject[someStringVar]).
Hope this helps!
I guess it depends on what you want. For simple objects, I guess you could use the second methods. When your objects grow larger and you're planning on using similar objects, I guess the first method would be better. That way you can also extend it using prototypes.
Example:
function Circle(radius) {
this.radius = radius;
}
Circle.prototype.getCircumference = function() {
return Math.PI * 2 * this.radius;
};
Circle.prototype.getArea = function() {
return Math.PI * this.radius * this.radius;
}
I am not a big fan of the third method, but it's really useful for dynamically editing properties, for example var foo='bar'; var bar = someObject[foo];.
There are a many ways to create your objects in JavaScript.
Using a constructer function to create an object or object literal notation is using alot in JavaScript. Also creating an instance of Object and then adding properties and methods to it, there are three common ways to do create objects in JavaScript.
Constructer functions
There are built-in constructer functions that we all may use them time to time, like Date(), Number(), Boolean() etc, all constructer functions start with Capital letter, in the meantime we can create custom constructor function in JavaScript like this:
function Box (Width, Height, fill) {
this.width = Width; // The width of the box
this.height = Height; // The height of the box
this.fill = true; // Is it filled or not?
}
and you can invoke it, simply using new(), to create a new instance of the constructor, create something like below and call the constructor function with filled parameters:
var newBox = new Box(8, 12, true);
Object literals
Using object literals are very used case creating object in JavaScript, this an example of creating a simple object, you can assign anything to your object properties as long as they are defined:
var person = {
name: "Alireza",
surname: "Dezfoolian"
nose: 1,
feet: 2,
hands: 2,
cash: null
};
Prototyping
After creating an Object, you can prototype more members to that, for example adding colour to our Box, we can do this:
Box.prototype.colour = 'red';
While many people here say there is no best way for object creation, there is a rationale as to why there are so many ways to create objects in JavaScript, as of 2019, and this has to do with the progress of JavaScript over the different iterations of EcmaScript releases dating back to 1997.
Prior to ECMAScript 5, there were only two ways of creating objects: the constructor function or the literal notation ( a better alternative to new Object()). With the constructor function notation you create an object that can be instantiated into multiple instances (with the new keyword), while the literal notation delivers a single object, like a singleton.
// constructor function
function Person() {};
// literal notation
var Person = {};
Regardless of the method you use, JavaScript objects are simply properties of key value pairs:
// Method 1: dot notation
obj.firstName = 'Bob';
// Method 2: bracket notation. With bracket notation, you can use invalid characters for a javascript identifier.
obj['lastName'] = 'Smith';
// Method 3: Object.defineProperty
Object.defineProperty(obj, 'firstName', {
value: 'Bob',
writable: true,
configurable: true,
enumerable: false
})
// Method 4: Object.defineProperties
Object.defineProperties(obj, {
firstName: {
value: 'Bob',
writable: true
},
lastName: {
value: 'Smith',
writable: false
}
});
In early versions of JavaScript, the only real way to mimic class-based inheritance was to use constructor functions. the constructor function is a special function that is invoked with the 'new' keyword. By convention, the function identifier is capitalized, albiet it is not required. Inside of the constructor, we refer to the 'this' keyword to add properties to the object that the constructor function is implicitly creating. The constructor function implicitly returns the new object with the populated properties back to the calling function implicitly, unless you explicitly use the return keyword and return something else.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.sayName = function(){
return "My name is " + this.firstName + " " + this.lastName;
}
}
var bob = new Person("Bob", "Smith");
bob instanceOf Person // true
There is a problem with the sayName method. Typically, in Object-Oriented Class-based programming languages, you use classes as factories to create objects. Each object will have its own instance variables, but it will have a pointer to the methods defined in the class blueprint. Unfortunately, when using JavaScript's constructor function, every time it is called, it will define a new sayName property on the newly created object. So each object will have its own unique sayName property. This will consume more memory resources.
In addition to increased memory resources, defining methods inside of the constructor function eliminates the possibility of inheritance. Again, the method will be defined as a property on the newly created object and no other object, so inheritance cannot work like. Hence, JavaScript provides the prototype chain as a form of inheritance, making JavaScript a prototypal language.
If you have a parent and a parent shares many properties of a child, then the child should inherit those properties. Prior to ES5, it was accomplished as follows:
function Parent(eyeColor, hairColor) {
this.eyeColor = eyeColor;
this.hairColor = hairColor;
}
Parent.prototype.getEyeColor = function() {
console.log('has ' + this.eyeColor);
}
Parent.prototype.getHairColor = function() {
console.log('has ' + this.hairColor);
}
function Child(firstName, lastName) {
Parent.call(this, arguments[2], arguments[3]);
this.firstName = firstName;
this.lastName = lastName;
}
Child.prototype = Parent.prototype;
var child = new Child('Bob', 'Smith', 'blue', 'blonde');
child.getEyeColor(); // has blue eyes
child.getHairColor(); // has blonde hair
The way we utilized the prototype chain above has a quirk. Since the prototype is a live link, by changing the property of one object in the prototype chain, you'd be changing same property of another object as well. Obviously, changing a child's inherited method should not change the parent's method. Object.create resolved this issue by using a polyfill. Thus, with Object.create, you can safely modify a child's property in the prototype chain without affecting the parent's same property in the prototype chain.
ECMAScript 5 introduced Object.create to solve the aforementioned bug in the constructor function for object creation. The Object.create() method CREATES a new object, using an existing object as the prototype of the newly created object. Since a new object is created, you no longer have the issue where modifying the child property in the prototype chain will modify the parent's reference to that property in the chain.
var bobSmith = {
firstName: "Bob",
lastName: "Smith",
sayName: function(){
return "My name is " + this.firstName + " " + this.lastName;
}
}
var janeSmith = Object.create(bobSmith, {
firstName : { value: "Jane" }
})
console.log(bobSmith.sayName()); // My name is Bob Smith
console.log(janeSmith.sayName()); // My name is Jane Smith
janeSmith.__proto__ == bobSmith; // true
janeSmith instanceof bobSmith; // Uncaught TypeError: Right-hand side of 'instanceof' is not callable. Error occurs because bobSmith is not a constructor function.
Prior to ES6, here was a common creational pattern to utilize function constructors and Object.create:
const View = function(element){
this.element = element;
}
View.prototype = {
getElement: function(){
this.element
}
}
const SubView = function(element){
View.call(this, element);
}
SubView.prototype = Object.create(View.prototype);
Now Object.create coupled with constructor functions have been widely used for object creation and inheritance in JavaScript. However, ES6 introduced the concept of classes, which are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript. Thus, JavaScript remains a prototypal language.
ES6 classes make inheritance much easier. We no longer have to manually copy the parent class's prototype functions and reset the child class's constructor.
// create parent class
class Person {
constructor (name) {
this.name = name;
}
}
// create child class and extend our parent class
class Boy extends Person {
constructor (name, color) {
// invoke our parent constructor function passing in any required parameters
super(name);
this.favoriteColor = color;
}
}
const boy = new Boy('bob', 'blue')
boy.favoriteColor; // blue
All in all, these 5 different strategies of Object Creation in JavaScript coincided the evolution of the EcmaScript standard.
Of course there is a best way.Objects in javascript have enumerable and nonenumerable properties.
var empty = {};
console.log(empty.toString);
// . function toString(){...}
console.log(empty.toString());
// . [object Object]
In the example above you can see that an empty object actually has properties.
Ok first let's see which is the best way:
var new_object = Object.create(null)
new_object.name = 'Roland'
new_object.last_name = 'Doda'
//etc
console.log("toString" in new_object) //=> false
In the example above the log will output false.
Now let's see why the other object creation ways are incorrect.
//Object constructor
var object = new Object();
console.log("toString" in object); //=> true
//Literal constructor
var person = {
name : "Anand",
getName : function (){
return this.name
}
}
console.log("toString" in person); //=> true
//function Constructor
function Person(name){
this.name = name
this.getName = function(){
return this.name
}
}
var person = new Person ('landi')
console.log("toString" in person); //=> true
//Prototype
function Person(){};
Person.prototype.name = "Anand";
console.log("toString" in person); //=> true
//Function/Prototype combination
function Person2(name){
this.name = name;
}
Person2.prototype.getName = function(){
return this.name
}
var person2 = new Person2('Roland')
console.log("toString" in person2) //=> true
As you can see above,all examples log true.Which means if you have a case that you have a for in loop to see if the object has a property will lead you to wrong results probably.
Note that the best way it is not easy.You have to define all properties of object line by line.The other ways are more easier and will have less code to create an object but you have to be aware in some cases.
I always use the "other ways" by the way and one solution to above warning if you don't use the best way is:
for (var property in new_object) {
if (new_object.hasOwnProperty(property)) {
// ... this is an own property
}
}
Majorly there are 3 ways of creating Objects-
Simplest one is using object literals.
const myObject = {}
Though this method is the simplest but has a disadvantage i.e if your object has behaviour(functions in it),then in future if you want to make any changes to it you would have to change it in all the objects.
So in that case it is better to use Factory or Constructor Functions.(anyone that you like)
Factory Functions are those functions that return an object.e.g-
function factoryFunc(exampleValue){
return{
exampleProperty: exampleValue
}
}
Constructor Functions are those functions that assign properties to objects using "this" keyword.e.g-
function constructorFunc(exampleValue){
this.exampleProperty= exampleValue;
}
const myObj= new constructorFunc(1);
function Plant() {
this.country = "Mexico"
this.isOrganic = true;
}
function Fruit(fName, fColor) {
this.name = fName;
this.color = fColor;
}
Fruit.prototype = new Plant();
var abanana = new Fruit("Banana", "Yellow")
console.log(abanana.constructor)
So in my code, I was trying to play around with prototype inheritance. Each time I created a new instance of Fruit (var aFruit = new Fruit ()), the new instance’s prototype is assigned the prototype from the Fruit constructor, which is Fruit.prototype.
So why is abanana.constructor
not
[function: Fruit]
but
[function: Plant]?
I thought this was what the constructor method does:
Moreover, all objects that inherit from another object also inherit a constructor property. And this constructor property is simply a property (like any variable) that holds or points to the constructor of the object.
Two problems with that code:
Using new Plant() to create the Fruit.prototype is a sadly-common anti-pattern; instead, use Object.create and call Plant from within Fruit. It doesn't matter a lot in your specific code, but it would matter if you wanted to derive something from Fruit, or if you wanted to make country an argument to Plant.
You need to set constructor on Fruit.prototype if you want it to point to Fruit.
So:
function Plant() {
this.country = "Mexico"
this.isOrganic = true;
}
function Fruit(fName, fColor) {
Plant.call(this); // **
this.name = fName;
this.color = fColor;
}
Fruit.prototype = Object.create(Plant.prototype); // **
Fruit.prototype.constructor = Fruit; // **
Of course, as of ES2015, we have class syntax, which you can use today with a transpiler (or if you only need to support current versions of Chrome and Firefox):
class Plant {
constructor() {
this.country = "Mexico";
this.isOrganic = true;
}
class Fruit extends Plant {
constructor(fName, fColor) {
super();
this.name = fName;
this.color = fColor;
}
}
I thought this was what the constructor method does:
Moreover, all objects that inherit from another object also inherit a constructor property. And this constructor property is simply a property (like any variable) that holds or points to the constructor of the object.
constructor isn't a method, it's a property that refers to the function that the prototype object is related to. JavaScript itself doesn't use constructor for anything at all, but does define that for all functions that have a prototype property, when the function is first created, the object that prototype property points to will have a constructor property pointing back at the function. But since you replace the value of prototype with a reference to a different object, you have to update the constructor property so it points back to the correct function again (if you want to be thorough, which is for the best — even though JavaScript doesn't use it, it doesn't mean that libraries don't use it).
On really old browsers, you may have to shim Object.create. It can't be completely shimmed, but it can be sufficient for the above:
if (!Object.create) {
Object.create = function(p, props) {
if (typeof props !== "undefined") {
throw new Error("The second argument of Object.create cannot be shimmed.");
}
function ctor() { }
ctor.prototype = p;
return new ctor;
};
}
When reading https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call for the section "Using call to chain constructors for an object":
function Product(name, price) {
this.name = name;
this.price = price;
if (price < 0)
throw RangeError('Cannot create product "' + name + '" with a negative price');
return this;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
Food.prototype = Object.create(Product.prototype);
function Toy(name, price) {
Product.call(this, name, price);
this.category = 'toy';
}
Toy.prototype = Object.create(Product.prototype);
var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);
I have read that a object's prototype is actually a object itself that points to the constructor's properties memory locations.
In function Food(name, price) it inherits the constructor's Product's properties with Product.call(this). What is Food.prototype = Object.create(Product.prototype); doing? Is it adding another prototype to Food(if that is even possible to have 2 prototypes)? Or is it appending to Food's prototype with the same prototype values of Product(which it already inherited so doesn't make sense to me ether)?
The essence of the problem cam be summarized as "why would you need to set prototypes at all"? In other words, why this is not sufficient to call the base class constructor and not to set the prototype?
The trick is that you could possibly not set the child class function's prototype! Your trivial example would work fine without it. Comment out the line and you will find that the code works with and without this line:
Food.prototype = Object.create(Product.prototype);
This is because all your object properties are set in constructors and by chaining constructors (calling the base class constructor) you have all the properties set on child class instances.
Consider however this:
function Base() {
this.BaseClassMethod = function() {}
}
vs
function Base() {
}
Base.prototype.BaseClassMethod = function() {}
As you can see, there are no fields but a method. Semantically, both snippets define a constructor function that creates instances having the sole BaseClassMethod method. However, in the first snippet there is a new extra function created for each created instance of the class, while in the second snippet the method definition is shared.
This very simple example shows that the same semantics can be achieved in different ways that have different profiles - in the above example is was at least the different memory footprint.
Yet another difference between these two is that in the latter, the function can be redefined somewhere in the future and the new version affects all previously created instances while in the first snippet what you can do is to change the definition in specific instances but not easily "in all previously created instances".
Whether or not this is your goal is another story. You can freely choose between these two ways of assigning methods to classes.
And there lies the answer to your question: without setting the prototype chain, methods defined in base class prototype (the latter snippet) would not be inherited if you only called the base class constructor from the child class constructor.
In other words, calling both the base class constructor and setting the prototype chain makes your inheritance independent on the way methods are defined in the base class.
Let's let code speak for itself. Object.create basically does this:
Object.create = function (o) {
//Object.create equals an anonymous function that accepts one parameter, 'o'.
function F() {};
//Create a new function called 'F' which is just an empty object.
F.prototype = o;
//the prototype of the 'F' function should point to the
//parameter of the anonymous function.
return new F();
//create a new constructor function based off of the 'F' function.
};
Hope this helps. Cheers
Food.prototype = Object.create(Product.prototype) is like extends in other languages. Product.call(this) is like super. With a helper and following conventions it helps to see this relation:
Function.prototype.inherits = function(parent) {
this.prototype = Object.create(parent.prototype); // inherit parent's prototype
this.prototype.constructor = this; // point to the right constructor
};
// A "class"
var Product = (function(){
// constructor
function Product(name, price) {
this.name = name;
this.price = price;
}
return Product;
}());
var Food = (function(_super){
Food.inherits(Product); // inherit Product's prototype methods
function Food(name, price) {
// call "super" to inherit instance properties
_super.call(this, name, price);
this.category = 'food';
}
}(Product)); // the parent class AKA "super"
It is not 100% equivalent, but this should give you a general idea of how inheritance works in JS compared to other languages. It can look pretty similar as you see.
In function Food(name, price) it inherits the constructor's Product's properties with Product.call(this).
Not really. It applies the Product's constructor to the new Food instance, executing its code with e.g. the negative price check.
A "byproduct" is that the constructor creates instance-specific properties on the object, yes.
What is Food.prototype = Object.create(Product.prototype); doing? Is it adding another prototype to Food(if that is even possible to have 2 prototypes)?
Exactly. It is chaining the prototypes. The instances of Food that are created by new Food will inherit properties (including methods) from Food.prototype, which will (by that statement) inherit properties from Product.prototype.
You can't see much of this behaviour currently as your prototype objects do not have any methods yet. Add some (maybe an "output" method?) and check the results.
Simple minimalistic inheritance library: (2kb minified) https://github.com/haroldiedema/joii
It basically allows you to do the following (and more):
// First (bottom level)
var Person = new Class(function() {
this.name = "Unknown Person";
});
// Employee, extend on Person & apply the Role property.
var Employee = new Class({ extends: Person }, function() {
this.name = 'Unknown Employee';
this.role = 'Employee';
this.getValue = function() {
return "Hello World";
}
});
// 3rd level, extend on Employee. Modify existing properties.
var Manager = new Class({ extends: Employee }, function() {
// Overwrite the value of 'role'.
this.role = this.role + ': Manager';
// Class constructor to apply the given 'name' value.
this.__construct = function(name) {
this.name = name;
}
// Parent inheritance & override
this.getValue = function() {
return this.parent.getValue().toUpperCase();
}
});
// And to use the final result:
var myManager = new Manager("John Smith");
console.log( myManager.name ); // John Smith
console.log( myManager.role ); // Manager
console.log( myManager.getValue() ); // HELLO WORLD
According to this article it should be a Javascript 2.0 way to define class. However, I never saw that in practice. Thus the question. How to use class keyword and what is the difference between Javascript 1.x way of doing things?
I know this is a old post, but as of today i.e with the advent of ECMAScript 6 we can declare javascript classes.
The syntax goes as follows :
class Person{
constructor(name){
this.name = name;
}
printName(){
console.log('Name is '+this.name);
}
}
var john = new Person('John Doe');
john.printName(); // This prints 'Name is John Doe'
A complete guide to this can be found in this post
The reason you never saw the class keyword used in practice is that all the current implementations of JavaScript are 1.x.
JavaScript 2.0 was merged into ECMAScript 4 which was rather unpopular and so never made it into the real world.
So to answer your question, how do you use the class keyword? You can't.
Summary
In ES6 the class keyword was introduced. The class keyword is no more than syntactic sugar on top of the already existing prototypal inheritance pattern. Classes in javascript is basically another way of writing constructor functions which can be used in order to create new object using the new keyword.
Example
class Person {
constructor(name) {
this.name = name;
}
talk() { console.log('hi'); }
}
const me = new Person('Willem');
console.log(typeof Person)
// logs function, Person class is just another constructor function under the hood
console.log(me.__proto__ === Person.prototype)
// logs true, classes just use the same prototypal inheritance pattern which is used by constructor functions.
// An object created with the new keyword gets a __proto__ property on it which is a reference to the prototype property on a constructor function.
In the above sample there can be observed in the first log that classes create from the class keyword actually are functions under the hood.
console.log(typeof Person) // logs 'function'
es6 classes use the same prototypal inheritance pattern which is used by constructor functions. Here is another example to demonstrate this behavior:
class Dog {
constructor (name) {
this.name = name;
}
bark () { console.log('bark') };
}
let doggie = new Dog('fluffy');
doggie.bark(); // logs bark
Dog.prototype.bark = () => console.log('woof');
// changing the prototype of Dog, doggie refers to this with its __proto__ property.
//Therefore doggie bark method has also changed.
doggie.bark(); // logs woof
The takeaway in the above example is that the bark method of any dog instance can be changed at runtime. This is because the bark method of any object created with the Dog class is just referring to this function.
You never saw it in practice because virtually nothing supports JavaScript 2.0. That draft is from a specification that died before being anything other than draft.
You can still build classes in JS of course using prototype!
var foo = function() {
this.hurrah = "yay!";
return this;
}
foo.prototype.doit() {
alert(this.hurrah);
}
If you've a Java or C# background, here's how to define a class in JavaScript
var MyClass = function (f, l){//constructor
//private members
var firstName = f,
lastName = l,
fullName = function () { //fullName is a private function
return firstName + " " + lastName;
};
return {
//public members
getFullName: fullName
};
}
var output = document.getElementById('Output'); //<div id="Output"></div>
var myName = new MyClass("First", "Last");
output.innerHTML = myName.getFullName();
Just to add the ECMA5 way of class making.
Note that it does not have a constructor function this way (but you can trigger an init function if you like)
var Class = {
el: null,
socket: null,
init: function (params) {
if (!(this.el instanceof HTMLElement)) {
throw new Error('Chat room has no DOM element to attach on.');
}
return this.doStuff();
},
doStuff: function (params) {
return this;
}
};
var instanceofClass = Object.create(Class, {
el: {
value: document.body.querySelector('.what ever')
},
someMoreData: {
value: [0,5,7,3]
}
}).init();