JavaScript - interesting trick, it is possible to create both class and function in one definition
In this article, we're going to have a look at how to create class that allows user to create object with or without new
operator in JavaScript.
Problem overview:
function MyClass() { }
var object1 = MyClass();
var object2 = new MyClass(); // <----- how to make new operator optional?
Simple problem solutions are presented below:
1. Optional new operator for class object with strict mode example
In this case recept how to make new object for same class definition with and without new
keyword with strict mode is described.
Note: these approach work for web broser and NodeJS JavaScript with strict mode.
1.1. this
or new object example
When this
is not defined new object is cteated and assigned to self
variable - it means ClassFunction
was called as function.
// ONLINE-RUNNER:browser;
'use strict'; // optional for NodeJS
var ClassFunction = function() {
var self = this || { };
self.printText = function(text) {
console.log(text);
};
return self;
};
var object1 = ClassFunction();
var object2 = new ClassFunction();
object1.printText('This text comes from function result object!');
object2.printText('This text comes from class instance object!');
1.2. Using instanceof
operator example
Below example shows how to detect if new
keyword were used to create ClassFunction
.
// ONLINE-RUNNER:browser;
'use strict';
var ClassFunction = function() {
var self = this;
if (self instanceof ClassFunction) {
self.printText = function(text) {
console.log(text);
};
} else {
return new ClassFunction();
}
};
var object1 = ClassFunction();
var object2 = new ClassFunction();
object1.printText('This text comes from function result object!');
object2.printText('This text comes from class instance object!');
2. Optional new operator for class object without strict mode example
In this case recept how to make new object for same class definition with and without new
keyword without strict mode is described.
2.1. Dedicated runtime environment example
Note: this approach requires to adjust source code for web browser or node js - look on comment - to solve this problem check example 2.
// ONLINE-RUNNER:browser;
var ClassFunction = function() {
var self = (this == window || this == null ? {} : this); // for web browser
// var self = (this == global || this == null ? {} : this); // for nodejs
self.printText = function(text) {
console.log(text);
};
return self;
};
var object1 = ClassFunction();
var object2 = new ClassFunction();
object1.printText('This text comes from function result object!');
object2.printText('This text comes from class instance object!');
2.2. Web browser or NodeJS auto detecting
This universal approach is useful to write code for web browser and node js both.
// ONLINE-RUNNER:browser;
function getRoot() {
if (typeof window != 'undefined') {
return window;
}
if (typeof global != 'undefined') {
return global;
}
throw new Error('Unsupported platform!');
}
var root = getRoot();
root.createScope = function(self) {
return (self == root ? { } : self);
};
// Example:
var ClassFunction = function() {
var self = createScope(this);
self.printText = function(text) {
console.log(text);
};
return self;
}
var object1 = ClassFunction();
var object2 = new ClassFunction();
object1.printText('This text comes from function result object!');
object2.printText('This text comes from class instance object!');