I am wondering what's the difference between function and class. Both using the keyword function, is there obvious distinction between those two?
Functions do specific things, classes are specific things. Classes often have methods, which are functions that are associated with a particular class, and do things associated with the thing that the class is - but if all you want is to do something, a function is all you need.
Functions are first-class in JavaScript, and they can have properties or be properties of other objects. A class constructor creates an instance of the class. A constructor in JavaScript is just a plain old function that returns an object.
As a rule of thumb, when you have a set of data with a specific structure and you want to perform specific methods on it, use a class. That is only valid, however, if you use multiple data structures in your code. If your whole code won't ever deal with more than one structure.
Classes are in fact "special functions", and just as you can define function expressions and function declarations, the class syntax has two components: class expressions and class declarations.
There is technically no class, they're both just functions. Any function can be invoked as a constructor with the keyword new
and the prototype property of that function is used for the object to inherit methods from.
"Class" is only used conceptually to describe the above practice.
So when someone says to you "make a color class" or whatever, you would do:
function Color(r, g, b) { this.r = r; this.g = g; this.b = b; } Color.prototype.method1 = function() { }; Color.prototype.method2 = function() { };
When you break it down, there is simply a function and some assignments to a property called prototype
of that function, all generic javascript syntax, nothing fancy going on.
It all becomes slightly magical when you say var black = new Color(0,0,0)
. You would then get an object with properties .r
, .g
and .b
. That object will also have a hidden [[prototype]] link to Color.prototype
. Which means you can say black.method1()
even though .method1()
does not exist in the black
object.
JavaScript is the most popular implementation of the ECMAScript Standard. The core features of Javascript are based on the ECMAScript standard, but Javascript also has other additional features that are not in the ECMA specifications/standard. Every browser has a JavaScript interpreter.
Overview
« ECMAScript was originally designed to be a Web scripting language, providing a mechanism to enliven Web pages in browsers and to perform server computation as part of a Web-based client-server architecture. A scripting language is a programming language that is used to manipulate, customize, and automate the facilities of an existing system.
ECMAScript is an object-oriented programming language for performing computations and manipulating computational objects within a host environment. A web browser provides an ECMAScript host environment for client-side computation including, for instance, objects that represent windows, menus, pop-ups, dialog boxes, text areas, anchors, frames, history, cookies, and input/output.
ECMAScript is object-based: basic language and host facilities are provided by objects, and an ECMAScript program is a cluster of communicating objects
Objects «
Each constructor is a function that has a property named “prototype”
that is used to implement prototype-based inheritance and shared properties.
Every object created by a constructor has an implicit reference (called the object’s prototype) to the value of its constructor’s “prototype”
property. Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain
.
JavaScript treats functions as first-class objects, so being an object, you can assign properties to a function.
Hoisting is the JavaScript interpreter’s action of moving all variable and function declarations to the top of the current scope. Function Hoisting, declarations & expressions
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody }
ES5 Function:
function Shape(id) { // Function Declaration this.id = id; }; // prototype was created automatically when we declared the function Shape.hasOwnProperty('prototype'); // true // Adding a prototyped method to a function. Shape.prototype.getID = function () { return this.id; }; var expFn = Shape; // Function Expression console.dir( expFn () ); // Function Executes and return default return type - 'undefined'
To a function if the return value is not specified, then undefined
is returned. If the function is invoked with new
and the return value is not an object, then this (the new object) is returned.
NOTE: A prototype property is automatically created for every function, to allow for the possibility that the function will be used as a constructor.
constructor
« Function object that creates and initializes objects.prototype
« object that provides shared properties for other objects.__proto__
« The proto property which points to its super object's prototype. If you open it up you will see that proto points to its super object variables and functions.
To access prototype methods of above crated function, we need to create object using new
keyword along with constructor function
. if you are creating Shape - Object
using new
keyword then it has an internal (or) private link
to function's prototype Shape
.
ES5 Constructor Function Classes: Function objects created using Function.prototype.bind
Shape.prototype.setID = function ( id ) { this.id = id; }; var funObj = new Shape( ); funObj.hasOwnProperty('prototype'); // false funObj.setID( 10 ) console.dir( funObj ); console.log( funObj.getID() ); /* expFun funObj name: "Shape" id: 10 prototype:Object constructor: function Shape(id) getID: function() setID: function( id ) __proto__: function () __proto__: Object constructor: function Shape(id) getID: function() setID: function( id ) <function scope> */
ES6 introduced Arrow function: An arrow function expression has a shorter syntax than a function expression and does not bind its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors. ArrowFunction grammar production do not have a prototype property.
ArrowFunction : ArrowParameters => ConciseBody
a => (a < 10) ? 'valid' : 'invalid' const fn = (item) => { return item & 1 ? 'Odd' : 'Even'; }; console.log( fn(2) ); // Even console.log( fn(3) ); // Odd
In a class-based object-oriented language, in general, state is carried by instances, methods are carried by classes, and inheritance is only of structure and behavior. In ECMAScript, the state and methods are carried by objects, and structure, behavior, and state are all inherited.
Babel is a JavaScript compiler. Use it to Transform
ES6
toES5
formatBABEL JS
(or)ES6Console
.
ES6 Classes: ES2015 classes
are a simple sugar over the prototype-based OO pattern. Having a single convenient declarative form makes class patterns easier to use, and encourages interoperability. Classes support prototype-based inheritance, super calls, instance and static methods and constructors.
class Shape { constructor(id) { this.id = id } get uniqueID() { return this.id; } set uniqueID(changeVal) { this.id = changeVal; } } Shape.parent_S_V = 777; // Class Inheritance class Rectangle extends Shape { constructor(id, width, height) { super(id) this.width = width this.height = height } // Duplicate constructor in the same class are not allowed. /*constructor (width, height) { this._width = width; this._height = height; }*/ get area() { console.log('Area : ', this.width * this.height); return this.width * this.height } get globalValue() { console.log('GET ID : ', Rectangle._staticVar); return Rectangle._staticVar; } set globalValue(value) { Rectangle._staticVar = value; console.log('SET ID : ', Rectangle._staticVar); } static println() { console.log('Static Method'); } // this.constructor.parent_S_V - Static property can be accessed by it's instances setStaticVar(staticVal) { // https://sckoverflow.com/a/42853205/5081877 Rectangle.parent_S_V = staticVal; console.log('SET Instance Method Parent Class Static Value : ', Rectangle.parent_S_V); } getStaticVar() { console.log('GET Instance Method Parent Class Static Value : ', Rectangle.parent_S_V); return Rectangle.parent_S_V; } } Rectangle._staticVar = 77777; var objTest = new Rectangle('Yash_777', 8, 7); console.dir( objTest );
ES5 Function Classes: uses Object.defineProperty ( O, P, Attributes )
The
Object.defineProperty()
method defines a new property directly on an object, or modifies an existing property on an object, and returns the object.Function instances that can be used as a constructor have a prototype property.
This property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }.
'use strict'; var Shape = function ( superClass ) { var currentClass = Shape; _inherits(currentClass, superClass); // Prototype Chain - Extends function Shape(id) { superClass.call(this); // Linking with SuperClass Constructor. // Instance Variables list. this.id = id; return this; } var staticVariablesJOSN = { "parent_S_V" : 777 }; staticVariable( currentClass, staticVariablesJOSN ); // Setters, Getters, instanceMethods. [{}, {}]; var instanceFunctions = [ { key: 'uniqueID', get: function get() { return this.id; }, set: function set(changeVal) { this.id = changeVal; } } ]; instanceMethods( currentClass, instanceFunctions ); return currentClass; }(Object); var Rectangle = function ( superClass ) { var currentClass = Rectangle; _inherits(currentClass, superClass); // Prototype Chain - Extends function Rectangle(id, width, height) { superClass.call(this, id); // Linking with SuperClass Constructor. this.width = width; this.height = height; return this; } var staticVariablesJOSN = { "_staticVar" : 77777 }; staticVariable( currentClass, staticVariablesJOSN ); var staticFunctions = [ { key: 'println', value: function println() { console.log('Static Method'); } } ]; staticMethods(currentClass, staticFunctions); var instanceFunctions = [ { key: 'setStaticVar', value: function setStaticVar(staticVal) { currentClass.parent_S_V = staticVal; console.log('SET Instance Method Parent Class Static Value : ', currentClass.parent_S_V); } }, { key: 'getStaticVar', value: function getStaticVar() { console.log('GET Instance Method Parent Class Static Value : ', currentClass.parent_S_V); return currentClass.parent_S_V; } }, { key: 'area', get: function get() { console.log('Area : ', this.width * this.height); return this.width * this.height; } }, { key: 'globalValue', get: function get() { console.log('GET ID : ', currentClass._staticVar); return currentClass._staticVar; }, set: function set(value) { currentClass._staticVar = value; console.log('SET ID : ', currentClass._staticVar); } } ]; instanceMethods( currentClass, instanceFunctions ); return currentClass; }(Shape); // ===== ES5 Class Conversion Supported Functions ===== function defineProperties(target, props) { console.log(target, ' : ', props); for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function staticMethods( currentClass, staticProps ) { defineProperties(currentClass, staticProps); }; function instanceMethods( currentClass, protoProps ) { defineProperties(currentClass.prototype, protoProps); }; function staticVariable( currentClass, staticVariales ) { // Get Key Set and get its corresponding value. // currentClass.key = value; for( var prop in staticVariales ) { console.log('Keys : Values'); if( staticVariales.hasOwnProperty( prop ) ) { console.log(prop, ' : ', staticVariales[ prop ] ); currentClass[ prop ] = staticVariales[ prop ]; } } }; function _inherits(subClass, superClass) { console.log( subClass, ' : extends : ', superClass ); if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var objTest = new Rectangle('Yash_777', 8, 7); console.dir(objTest);
Below code snippet is to test about Each instance has their own copy of instance members and common static members.
var obj1 = new Rectangle('R_1', 50, 20); Rectangle.println(); // Static Method console.log( obj1 ); // Rectangle {id: "R_1", width: 50, height: 20} obj1.area; // Area : 1000 obj1.globalValue; // GET ID : 77777 obj1.globalValue = 88; // SET ID : 88 obj1.globalValue; // GET ID : 88 var obj2 = new Rectangle('R_2', 5, 70); console.log( obj2 ); // Rectangle {id: "R_2", width: 5, height: 70} obj2.area; // Area : 350 obj2.globalValue; // GET ID : 88 obj2.globalValue = 999; // SET ID : 999 obj2.globalValue; // GET ID : 999 console.log('Static Variable Actions.'); obj1.globalValue; // GET ID : 999 console.log('Parent Class Static variables'); obj1.getStaticVar(); // GET Instance Method Parent Class Static Value : 777 obj1.setStaticVar(7); // SET Instance Method Parent Class Static Value : 7 obj1.getStaticVar(); // GET Instance Method Parent Class Static Value : 7
Major Differences between functions and classes are:
- Function Declarations get
Hoisted
to Top of the context, where as classes declarations and function Expressions are not Hoisted.- Function Declarations, Expression can be
Overridden
as they are like a Variable -var
if multiple declaration are available then it overrides its parent scope. Where as the Classes are not Overridden they are likelet
|const
, let doesn't allows multiple declaration with same name inside its scope.- Function's / classes allows only single constructor for its object scope.
Computed method names
are allowed to ES6 classes having class keyword, but function keyword is not allows itfunction myFoo() { this.['my'+'Method'] = function () { console.log('Computed Function Method'); }; } class Foo { ['my'+'Method']() { console.log('Computed Method'); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With