Skip to content

Instantly share code, notes, and snippets.

@tomchen
Last active April 8, 2020 22:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomchen/1850ff92f9bf494ba625cbf2843ec1d8 to your computer and use it in GitHub Desktop.
Save tomchen/1850ff92f9bf494ba625cbf2843ec1d8 to your computer and use it in GitHub Desktop.
ES6 class vs ES5 constructor function
//ES6 class vs ES5 constructor function
// ES6 class
class MyClass {
// is executed upon instantiation, not to be used as a normal method
// proposal class properties
// https://babeljs.io/docs/en/babel-plugin-proposal-class-properties
// https://github.com/tc39/proposal-class-fields
publicVariable = "public variable";
#privateVariable = "private variable";
static staticPublicVariable = "static public variable";
static #staticPrivateVariable = "static private variable";
constructor(arg1, arg2) {
console.log("constructor executed!");
var _privateVarInConstructor = "private var in constructor";
this.publicVar = "public var";
// The only privilege ES5 constructor function's privileged method has
// comparing to normal public method is: to access _privateVarInClass, arg1(, arg2...), and _privateVarInConstructor
this.privilegedMethod = function() {
// here shows the context during a "normal" call, it could change when it's called differently (such as using bind/apply/call). Same as below
console.log(this === myclassinstance); // true
// the following tests have exactly the same output as the tests in constructor
console.log(this.constructor === MyClass); // true
try{ console.log(_privateVarInConstructor); }catch(e){console.log("NOT DECLARED");} // private var in constructor
try{ console.log(arg1); }catch(e){console.log("NOT DECLARED");} // arg 1
try{ console.log(publicVar); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ console.log(this.publicVar); }catch(e){console.log("NOT DECLARED");} // public var
try{ console.log(MyClass.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.method2(); }catch(e){console.log("NOT DECLARED");} // method2 executed!
try{ MyClass.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ MyClass.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // staticMethod2 executed!
}
// access to the variables and methods outside the constructor is exactly the same as normal public method
console.log(this); // the context (this) is the newly created instance of the class and will later be referenced by the variable "myclassinstance"
console.log(this.constructor === MyClass); // true
try{ console.log(_privateVarInConstructor); }catch(e){console.log("NOT DECLARED");} // private var in constructor
try{ console.log(arg1); }catch(e){console.log("NOT DECLARED");} // arg 1
try{ console.log(publicVar); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ console.log(this.publicVar); }catch(e){console.log("NOT DECLARED");} // public var
try{ console.log(MyClass.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.method2(); }catch(e){console.log("NOT DECLARED");} // method2 executed!
try{ MyClass.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ MyClass.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // staticMethod2 executed!
}
// var _privateVarInClass = "private var in class"; // not allowed in ES6, OK in ES5
// var _privateMethod = function() { // not allowed in ES6, OK in ES5
// };
publicMethod0 = () => {} // NOT yet supported by lastest Chrome
publicMethod() {}
#privateMethod() {} // NOT yet supported by lastest Chrome (privateVariable is supported)
static staticPublicMethod() {}
static #staticPrivateMethod() {} // NOT yet supported by lastest Chrome (staticPrivateVariable is supported)
// normal public method, to be called with myclassinstance.method1();
method1() {
console.log(this === myclassinstance); // true
console.log(this.constructor === MyClass); // true
try{ console.log(_privateVarInConstructor); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED // can't access _privateVarInConstructor by any means
try{ console.log(arg1); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED // can't access arg1 by any means
try{ console.log(publicVar); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ console.log(this.publicVar); }catch(e){console.log("NOT DECLARED");} // public var
try{ console.log(MyClass.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.method2(); }catch(e){console.log("NOT DECLARED");} // method2 executed!
try{ MyClass.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ MyClass.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // staticMethod2 executed!
}
method2() {
console.log("method2 executed!");
}
// static public method, to be called only with MyClass.staticMethod1();
static staticMethod1() {
console.log(this === MyClass); // true
console.log(this.constructor === Function); // true
try{ console.log(_privateVarInConstructor); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED // can't access _privateVarInConstructor by any means
try{ console.log(arg1); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED // can't access arg1 by any means
try{ console.log(publicVar); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ console.log(this.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(this.constructor.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.constructor.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // staticMethod2 executed!
try{ this.constructor.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
}
static staticMethod2() {
console.log("staticMethod2 executed!");
}
static staticMethod2() {
console.log("staticMethod2 executed!");
}
// static staticVariable = 42; // proposed, not widely supported yet. (static variable is another name for static property here) We can either use MyClass.staticVariable outside the class, or use:
// static get staticVariable() {
// return 5;
// }
}
console.log(" ========== BEGINNING OF var myclassinstance = new MyClass(); ========== ");
var myclassinstance = new MyClass("arg 1");
console.log(" ========== END OF var myclassinstance = new MyClass(); ========== ");
// MyClass.method1(); // can't access
console.log(" ========== BEGINNING OF myclassinstance.method1(); ========== ");
myclassinstance.method1();
console.log(" ========== END OF myclassinstance.method1(); ========== ");
// myclassinstance.staticMethod1(); // can't access
console.log(" ========== BEGINNING OF MyClass.staticMethod1(); ========== ");
MyClass.staticMethod1();
console.log(" ========== END OF MyClass.staticMethod1(); ========== ");
// MyClass.privilegedMethod(); // can't access
console.log(" ========== BEGINNING OF myclassinstance.privilegedMethod(); ========== ");
myclassinstance.privilegedMethod();
console.log(" ========== END OF myclassinstance.privilegedMethod(); ========== ");
console.log(MyClass.prototype); // { constructor: ..., method1: ..., method2: ..., ...}
// ES5 constructor function
"use strict";
var UrClass = function () {
// is executed upon instantiation, not to be used as a normal method
function UrClass(arg1, arg2) {
if (!(this instanceof UrClass)) { throw new TypeError("Cannot call a class as a function"); } // added to simulate the class' behaviour in ES6
console.log("constructor executed!");
var _privateVarInConstructor = "private var in constructor";
this.publicVar = "public var";
// The only privilege ES5 constructor function's privileged method has
// comparing to normal public method is: to access _privateVarInClass, arg1(, arg2...), and _privateVarInConstructor
this.privilegedMethod = function () {
// here shows the context during a "normal" call, it could change when it's called differently (such as using bind/apply/call). Same as below
console.log(this === urclassinstance); // true
// the following tests have exactly the same output as the tests in constructor
console.log(this.constructor === UrClass); // true
try{ console.log(_privateVarInConstructor); }catch(e){console.log("NOT DECLARED");} // private var in constructor
try{ console.log(arg1); }catch(e){console.log("NOT DECLARED");} // arg 1
try{ console.log(publicVar); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ console.log(this.publicVar); }catch(e){console.log("NOT DECLARED");} // public var
try{ console.log(UrClass.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(_privateVarInClass); }catch(e){console.log("NOT DECLARED");} // private var in class
try{ console.log(this._privateVarInClass); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(UrClass._privateVarInClass); }catch(e){console.log("NOT DECLARED");} // undefined
try{ method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.method2(); }catch(e){console.log("NOT DECLARED");} // method2 executed!
try{ UrClass.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ UrClass.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // staticMethod2 executed!
};
// access to the variables and methods outside the constructor is exactly the same as normal public method
console.log(this); // the context (this) is the newly created instance of the class and will later be referenced by the variable "urclassinstance"
console.log(this.constructor === UrClass); // true
try{ console.log(_privateVarInConstructor); }catch(e){console.log("NOT DECLARED");} // private var in constructor
try{ console.log(arg1); }catch(e){console.log("NOT DECLARED");} // arg 1
try{ console.log(publicVar); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ console.log(this.publicVar); }catch(e){console.log("NOT DECLARED");} // public var
try{ console.log(UrClass.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(_privateVarInClass); }catch(e){console.log("NOT DECLARED");} // private var in class
try{ console.log(this._privateVarInClass); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(UrClass._privateVarInClass); }catch(e){console.log("NOT DECLARED");} // undefined
try{ method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.method2(); }catch(e){console.log("NOT DECLARED");} // method2 executed!
try{ UrClass.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ UrClass.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // staticMethod2 executed!
}
var _privateVarInClass = "private var in class"; // not allowed in ES6, OK in ES5
// not allowed in ES6, OK in ES5
// it can be called from anywhere inside the class
// (i.e. directly in the class (at the end) / in the privileged method /
// constructor / other private method / normal or static public method)
// the result is always the same as in the following comments
var _privateMethod = function() {
console.log(this); // Window
try{ console.log(_privateVarInConstructor); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ console.log(arg1); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ console.log(publicVar); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ console.log(this.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(UrClass.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(UrClass.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(_privateVarInClass); }catch(e){console.log("NOT DECLARED");} // private var in class
try{ console.log(this._privateVarInClass); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(UrClass._privateVarInClass); }catch(e){console.log("NOT DECLARED");} // undefined
try{ method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ UrClass.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ UrClass.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // staticMethod2 executed!
};
// normal public method, to be called with urclassinstance.method1();
UrClass.prototype.method1 = function() {
console.log(this === urclassinstance); // true
console.log(this.constructor === UrClass); // true
try{ console.log(_privateVarInConstructor); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED // can't access _privateVarInConstructor by any means
try{ console.log(arg1); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED // can't access arg1 by any means
try{ console.log(publicVar); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ console.log(this.publicVar); }catch(e){console.log("NOT DECLARED");} // public var
try{ console.log(UrClass.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(_privateVarInClass); }catch(e){console.log("NOT DECLARED");} // private var in class
try{ console.log(this._privateVarInClass); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(UrClass._privateVarInClass); }catch(e){console.log("NOT DECLARED");} // undefined
try{ method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.method2(); }catch(e){console.log("NOT DECLARED");} // method2 executed!
try{ UrClass.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ UrClass.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // staticMethod2 executed!
};
UrClass.prototype.method2 = function() {
console.log("method2 executed!");
};
// static public method, to be called only with UrClass.staticMethod1();
UrClass.staticMethod1 = function() {
console.log(this === UrClass); // true
console.log(this.constructor === Function); // true
try{ console.log(_privateVarInConstructor); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED // can't access _privateVarInConstructor by any means
try{ console.log(arg1); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED // can't access arg1 by any means
try{ console.log(publicVar); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ console.log(this.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(this.constructor.publicVar); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(_privateVarInClass); }catch(e){console.log("NOT DECLARED");} // private var in class
try{ console.log(this._privateVarInClass); }catch(e){console.log("NOT DECLARED");} // undefined
try{ console.log(UrClass._privateVarInClass); }catch(e){console.log("NOT DECLARED");} // undefined
try{ method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.constructor.method2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
try{ this.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // staticMethod2 executed!
try{ this.constructor.staticMethod2(); }catch(e){console.log("NOT DECLARED");} // NOT DECLARED
};
UrClass.staticMethod2 = function() {
console.log("staticMethod2 executed!");
};
//same goes for UrClass.staticVariable (static variable is another name for static property here)
return UrClass;
}();
console.log(" ========== BEGINNING OF var urclassinstance = new UrClass(); ========== ");
var urclassinstance = new UrClass("arg 1");
console.log(" ========== END OF var urclassinstance = new UrClass(); ========== ");
// UrClass.method1(); // can't access
console.log(" ========== BEGINNING OF urclassinstance.method1(); ========== ");
urclassinstance.method1();
console.log(" ========== END OF urclassinstance.method1(); ========== ");
// urclassinstance.staticMethod1(); // can't access
console.log(" ========== BEGINNING OF UrClass.staticMethod1(); ========== ");
UrClass.staticMethod1();
console.log(" ========== END OF UrClass.staticMethod1(); ========== ");
// UrClass.privilegedMethod(); // can't access
console.log(" ========== BEGINNING OF urclassinstance.privilegedMethod(); ========== ");
urclassinstance.privilegedMethod();
console.log(" ========== END OF urclassinstance.privilegedMethod(); ========== ");
console.log(UrClass.prototype); // { constructor: ..., method1: ..., method2: ..., ...}
// =============
// JS lib template
/*
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD, register as an anonymous module
define(factory);
} else if (typeof exports === 'object') {
// CommonJS
module.exports = factory();
} else {
// Browser
root.UrClass = factory();
}
}(this, function () {
'use strict';
function UrClass(arg1, arg2) {
var _privateVarInConstructor = "private var in constructor";
this.publicVar = "public var";
// ES5 constructor function's privileged method has
// only one privilege comparing to normal public method: to access _privateVarInClass
this.privilegedMethod = function() {
}
}
var _privateVarInClass = "private var in class";
var _privateMethod = function() {
};
// normal public method, to be called with urclassinstance.method1();
UrClass.prototype.method1 = function() {
};
// static public method, to be called only with UrClass.staticMethod1();
UrClass.staticMethod1 = function staticMethod1() {
};
return UrClass;
}));
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment