var A = function () {
this.someProperty = 0;
};
var a = new A();
The variable a is an object. What do I call to A? A class?
A is called a constructor function. Well, specifically, A is a variable that refers to a constructor function, but we don't usually get into that kind of mintuiae.
Sometimes people do call these "classes," because constructor functions aid in producing classes of objects (in the general sense, e.g., objects with common characteristics). But JavaScript doesn't have classes in the class-based OOP sense like Java or C#, it has a different inheritance mechanism called prototypical inheritance. (This is true even in ES2015 and beyond, where the keyword class is used to define a constructor function, the properties of the prototype it assigns objects when used with new, and sometimes properties on that function referring to other functions ["static methods"].)
Related
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
According to this, functions inherit from Function and Function from Function.prototype in turn:
The global Function object has no methods or properties of its own, however, since it is a function itself it does inherit some methods and properties through the prototype chain from Function.prototype.
What's the point of Function.prototype then? Why not move its properties to Function and let Function.prototype be undefined? Functions would be derived from Function instead.
Same goes for Object etc.
functions inherit from Function
You are quoting MDN loosely. What it actually says is:
function objects inherit from Function.prototype
Note that on the MDN page, the initial word "function" in the above sentence is capitalized, but only because it is at the beginning of the sentence, not because it is referring to the JS object Function. It is referring to regular old functions declared as function() { }.
Remember that MDN is written by mere mortals. I would prefer they did not use the words "inherit" and "inheritance", not to mention "derived". JS does not have the concept of inheritance in the strict sense of the word. If you use this terminology, you will end up confusing yourself. What JS has is prototypes associated with objects. When accessing a property on an object, if it is not found, the prototype is consulted. If not found there, since a prototype is also an object with a prototype, the prototype's prototype is consulted, and so on up the chain.
Therefore, the above sentence would better be written as "function objects have as their prototype Function.prototype".
The JS Function object is not directly associated with Function.prototype, other than the fact that Function.prototype is a property of Function, and, since the Function object is itself a function, it itself has Function.prototype as its prototype. Whatever properties may or may not be present on Function, or hung on it by you, have nothing to do with the prototype chain and are not "inherited" by anyone.
When you do (function() { }).call(), the call property/method is first looked up on the function object itself; if it does not exist there, as it normally would not, then it is looked up on the prototype assigned intrinsically when the function was declared, which is Function.prototype. Where else would you put methods such as call or apply if not on Function.prototype? What else would you call the prototype automatically assigned to functions other than Function.prototype?
As an aside, note that Function.call will resolve correctly to the internal call function. Why? Not because that is where call lives, or because that is from where regular functions "inherit" call, but rather because, since as I mentioned before, Function is itself a function, and therefore has the prototype Function.prototype, call can be found on its prototype chain.
What's the point of Function.prototype then? Why not move its properties to Function and let Function.prototype be undefined? Functions would be derived from Function instead.
X.prototype is a property on X used as the prototype for objects created using X as a constructor. Therefore, to assign the correct prototype to objects created using Function as a constructor (which includes functions declared as function x() { }), the prototype must be present as the prototype property on Function.
Functions on the prototype are only created once and shared between each instance. Functions created in the constructor are created as new objects for each new object created with the constructor.
As a general rule functions should be on the prototype since they will generally not be modified for different objects of the same type, and this has a slight memory/performance benefit. Other properties like objects and arrays should be defined in the constructor, unless you want to create a shared, static property, in which case you should use the prototype.
Its easier to see the distinctions with normal objects or arrays rather than functions
function Foo(){
this.bar = [];
}
var fooObj1 = new Foo();
var fooObj2 = new Foo();
fooObj1.bar.push("x");
alert(fooObj2.bar) //[]
as opposed to:
function Foo(){
}
Foo.prototype.bar = []
var fooObj1 = new Foo();
var fooObj2 = new Foo();
fooObj1.bar.push("x");
alert(fooObj2.bar) //["x"]
You need Function.prototype for if you want to extend functions, consider this:
Function.prototype.moo = 5;
function x() { };
console.log(x.moo); // 5
every function you make now has the property moo, versus:
Function.quack = 6;
function b() {};
console.log(b.quack); // undefined
This is not true if you just slap a property onto Function. Every function DOES NOT inherit properties assigned to Function, which is why you need Function.prototype.
The Javascript microlibrary augment.js is sometimes used to include OOP-like features in Javascript code. Despite working with Javascript on a daily basis I am still somewhat naive about the inner workings of the language, so I often rely on or borrow from patterns from other libraries to avoid pitfalls.
One function in the augment.js library is defclass, which is quite short:
augment.defclass = function (prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
};
My question is: how is this anything like defining a class? It looks like all it does is 1) set the prototype of the input's constructor to be the input itself, and then 2) return the constructor. What does that have to do with defining a class (or something like a class)?
A class defined like this:
var Thing = augment.defclass({
constructor: function () {
this.x = 5;
},
getX: function () {
return this.x;
}
});
A typical JavaScript constructor:
function Thing() {
this.x = 5;
}
Thing.prototype.getX = function () {
return this.x;
};
They both have the same effect, but the defclass version looks more familiar to users of other languages. One extracts the constructor from the prototype, and the other puts the prototype on the constructor.
how is this anything like defining a class?
The question you need to answer first is: What is a class in Javascript?
From: Object vs Class vs Function
As you must already be aware by now there are no classes in
JavaScript. Instead functions in JavaScript may be made to behave like
constructors by preceding a function call with the new keyword. This
is known as the constructor pattern.
From: JavaScript: The Good Parts Douglas Crockford, O'Reilly Media, 8 May 2008, page 29
If a function is invoked with the new prefix, then a new object will
be created with a hidden link to the value of the function's prototype
member, and this will be bound to that new object.
So again there are no classes - you have functions that can be invoked with new. If those functions have a prototype property, then the new objects created are inheriting from that prototype.
Everything you need to do to define a Javascript function to be used as a constructor is setting the properties you want instances to inherit on its prototype property and (as you pointed out in your question) augment.defclass is doing that.
The reason for having such a function has been already explained by minitech in his answer.
What would the difference be between Date.prototype.newFunction and Date.newFunction? I'm aware of how prototypal inheritance works in Javascript so I understand the prototype example, but the Date.newFunction throws me.
As I think you know, the prototype contains properties that will be automatically inherited by objects created via the constructor.
Date.newFunction is just a property on the constructor itself and it can only be accessed via Date.newFunction. It is not inherited by objects created via the constructor and is not accessible via a particular instance created by the constructor.
Some would say that Date.newFunction is analogous to a class static method in other languages. It's not a method attached to a particular instance, but more like a helper function for that object type. These types of methods typically do not operate on instance data and they could just as easily be global utility functions, but it is often cleaner from a namespace point-of-view to assign them as properties of the constructor.
For example, on the Javascript Date object, methods such as Date.now() and Date.parse() are examples of this type of static methods. You don't create an instance to use them, you just call them directly:
var tStart = Date.now();
One thing to remember is that any function in Javascript is an object too, so it can have arbitrary properties beyond just the .prototype property and using that capability for static methods is just one use.
Date.a = function () {
return 'Date.a';
};
Date.prototype.a = function () {
return 'Date.prototype.a';
};
Date.a(); // return 'Date.a'
var b = new Date();
b.a(); // return 'Date.prototype.a'
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