Type Definition
Every function is also a type, and new instances of these functions can be created with the "new" operator. Function declaration can behave like a constructor, and in this case is called a Constructor Function. In constructor functions, prototype methods and fields can be accessed.
function MyType(){
if (!(this instanceof MyType))
throw new Error("Constructor can't be called as a function");
}
var myInstance = new MyType();
MyType(); // Error: Constructor can't be called as a function
In Eclipse, object types can be easily inspected in the JavaScript perspective. Constructor, instance members, static members and inner functions are all separated in Outline View.
Instance Members
Instance members are accessed from instance objects which are created with the "new" operator. Instance members are created via "this" keyword, prototype, constructor closure or Object.defineProperty method.
function Cat(name){
var voice = "Meow";
this.name = name;
this.say = function(){
return voice;
}
}
Cat.prototype.eat = function(){
return "Eating";
}
var cat = new Cat("Fluffy");
Object.defineProperty(cat, "numLegs",{value: 4,writable:true,enumerable:true,configurable:true});
console.log(cat.name); // Fluffy
console.log(cat.numLegs); // 4
console.log(cat.say()); // Meow
console.log(cat.eat()); // Eating
Static Members
There is no direct support for static members. Constructor functions are used to create static members. Static members can't be accessed with "this" keyword.
Public Static Members:
function Factory(){
}
// public static method
Factory.getType = function (){
return "Object Factory";
};
// public static field
Factory.versionId = "F2.0";
Factory.prototype.test = function(){
console.log(this.versionId); // undefined
console.log(Factory.versionId); // F2.0
console.log(Factory.getType()); // Object Factory
}
var factory = new Factory();
factory.test();
Private Static Members:
var Book = (function () {
// private static field
var numOfBooks = 0;
// private static method
function checkIsbn(isbn) {
if (isbn.length != 10 && isbn.length != 13)
throw new Error("isbn is not valid!");
}
function Book(isbn, title) {
checkIsbn(isbn);
this.isbn = isbn;
this.title = title;
numOfBooks++;
this.getNumOfBooks = function () {
return numOfBooks;
}
}
return Book;
})();
var firstBook = new Book("0-943396-04-2", "First Title");
console.log(firstBook.title); // First Title
console.log(firstBook.getNumOfBooks()); // 1
var secondBook = new Book("0-85131-041-9", "Second Title");
console.log(firstBook.title); // First Title
console.log(secondBook.title); // Second Title
console.log(firstBook.getNumOfBooks()); // 2
console.log(secondBook.getNumOfBooks()); // 2
Abstract Types
JavaScript is a loosely typed language, so you don't have to specify the variable type of a variable when you declare it and pass as an argument. This reduces the need for abstract types like interfaces. But abstract types may be needed to collect common functionality when inheritance is used.
(function(){
var abstractCreateLock = false;
// abstract type
function BaseForm(){
if(abstractCreateLock)
throw new Error("Can't instantiate BaseForm!");
}
BaseForm.prototype = {};
BaseForm.prototype.post = function(){
throw new Error("Not implemented!");
}
function GridForm(){
}
GridForm.prototype = new BaseForm();
abstractCreateLock = true;
GridForm.prototype.post = function(){
// ...
return "Grid is posted.";
}
window.BaseForm = BaseForm;
window.GridForm = GridForm;
})();
var myGrid = new GridForm();
console.log(myGrid.post()); // Grid is posted.
var myForm = new BaseForm(); // Error: Can't instantiate BaseForm!
Interfaces
There is no direct interface or virtual class support in JavaScript. It can be mimicked as below, leaving a method signature check:
var Interface = function (name, methods) {
this.name = name;
// copies array
this.methods = methods.slice(0);
};
Interface.checkImplements = function (obj, interfaceObj) {
for (var i = 0; i < interfaceObj.methods.length; i++) {
var method = interfaceObj.methods[i];
if (!obj[method] || typeof obj[method] !== "function")
throw new Error("Interface not implemented! Interface: " + interfaceObj.name + " Method: " + method);
}
};
var iMaterial = new Interface("IMaterial", ["getName", "getPrice"]);
function Product(name,price,type){
Interface.checkImplements(this, iMaterial);
this.name = name;
this.price = price;
this.type = type;
}
Product.prototype.getName = function(){
return this.name;
};
Product.prototype.getPrice = function(){
return this.price;
};
var firstCar = new Product("Super Car X11",20000,"Car");
console.log(firstCar.getName()); // Super Car X11
delete Product.prototype.getPrice;
var secondCar = new Product("Super Car X12",30000,"Car"); // Error: Interface not implemented! Interface: IMaterial Method: getPrice
Singleton Objects
var Logger = {
enabled:true,
log: function(logText){
if(!this.enabled)
return;
if(console && console.log)
console.log(logText);
else
alert(logText);
}
}
Or
function Logger(){
}
Logger.enabled = true;
Logger.log = function(logText){
if(!Logger.enabled)
return;
if(console && console.log)
console.log(logText);
else
alert(logText);
};
Logger.log("test"); // test
Logger.enabled = false;
Logger.log("test"); //
{{ parent.title || parent.header.title}}
{{ parent.tldr }}
{{ parent.linkDescription }}
{{ parent.urlSource.name }}