Socket
Socket
Sign inDemoInstall

class-advanced

Package Overview
Dependencies
0
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    class-advanced

Universal JS classes helper - extending, constructors, static and dynamic elements, parent methods calls, self reflection, late static binding. For all browsers, Node.js, Windows Script Host and Adobe Javascript.


Version published
Weekly downloads
2
Maintainers
1
Install size
299 kB
Created
Weekly downloads
 

Readme

Source

Javascript Class (Class.js)

Latest Stable Version License

Universal JS library for prototyped classes - extending, constructor, static and dynamic elements, parent methods calls, self reflection and much more. For all browsers, Node.js and Windows Script Host.

INSTALATION

npm install oop-class

DOWNLOAD

<!-- for production: -->
<script type="text/javascript" src="https://tomflidr.github.io/class.js/builds/2.1.3/class.min.js"></script>

<!-- for development with JSDocs comments for IDE: -->
<script type="text/javascript" src="https://tomflidr.github.io/class.js/builds/2.1.3/class.dev.js"></script>

DEMOS

Features

  • very fast, effective, supersmall - all in 6.5 KB - minimized, 2.4 KB - gzipped
  • multi environment:
    • all browsers (MSIE6+, Safari, Opera, Chrome)
    • Node.js
    • WSH (Windows Script Host)
    • Adobe (only old archived version 0.6)
  • syntax customization - any declaration keyword or internal class keyword shoud be customized
  • inspired by PHP OOP, Ext.JS and Prototype.JS syntax
  • documented with JSDocs comments
  • Function.prototype.bind polyfill included
  • possibility to define:
    • Static elements
    • parent class by Extend keyword
    • Constructor method
    • all other elements as dynamic elements
  • possibility to call any dynamic and static parent method anywhere by:
    • this.parent(arguments); // in static and dynamic functions
    • this.parent(param1, param2); // in static and dynamic functions
    • this.parent.anyStaticMethod(param1, param2); // in static functions
    • this.parent.anyDynamicMethod(param1, param2); // in dynamic functions
    • this.parent.apply(this, [param1, param2]); // in static and dynamic functions
    • this.parent.anyStaticMethod.apply(this, [param1, param2]); // in static functions
    • this.parent.anyDynamicMethod.apply(this, [param1, param2]); // in dynamic functions
  • posibility to get current class definition by:
    • this.self; // without the need to know class name itself
    • this.static; // without the need to know class name itself
    • this.self context (static class definition) is changed in each defined dynamic and static method into value coresponded with original definition place
    • this.static context (static class definition) is not changed and it all time coresponds to original instance context - like Late Static Bindings in PHP OOP
  • posibility to get class name / fullname / namespace (only if class is defined by Class.Define();) by:
    • this.self.Fullname; or this.static.Fullname;
    • this.self.Name; or this.static.Name;
    • this.self.Namespace; or this.static.Namespace;
  • posibility to create instance by:
    • classic Javascript new keyword: var instance = new ClassName(param1, param2);
    • class name string with Class.Create(); method: var instance = Class.Create('ClassName', param1, param2);
  • inheritance checking by javascript 'instanceof' keyword
  • posibility to create anonymous classes like:
    • new Class({Constructor:function(text){console.log(text)}})("It works!");
  • Visual Studio - Go To Definition (F12) support - for current level objects and parent methods

1. Basic Class - Animal

// Declare not named class by Class(...) 
// call into custom variable 'Animal':
var Animal = Class({
	Constructor: function (name, sound) {
		this.name = name;
		this.sound = sound;
	},
	name: '',
	sound: '',
	MakeNoise: function () {
		console.log(this.sound);
	},
	IntroduceYourself: function () {
		console.log(
			"People call me '{0}'.".format(this.name)
		);
	}
});

// Create instance:
var dog = new Animal('Charlie', 'Wrr haf!');

// 'Wrr haf!'
dog.MakeNoise();

// 'People call me 'Charlie'.'
dog.IntroduceYourself();

2. Class Dog And Cat Extends Animal

// Declare named class by Class.Define(...) 
// call into global memory space as 'Animal'
Class.Define('Animal', {
	Static: {
		GetInstance: function () {
			// this.static contains a child class definition
			// as later static binding in PHP normaly works
			return new this.static(arguments);
		}
	},
	Constructor: function (name, sound) {
		this.name = name;
		this.sound = sound;
	},
	name: '',
	sound: '',
	MakeNoise: function () {
		console.log(this.sound);
	},
	IntroduceYourself: function () {
		console.log(
			"People call me '{0}'.".format(this.name)
		);
	},
	DefineYourself: function (asdf) {
		console.log(
			"Globaly, I'm an '{0}'.".format(this.self.Name)
			+ '<br />' +
			"More precisely, I'm a '{0}'.".format(this.static.Name)
			+ '<br />' +
			"I live like an '{0}'.".format(this.static.Namespace)
			+ '<br />' +
			"My namespace is '{0}'.".format(this.static.Fullname)
		);
	},
	TellYourStory: function () {
		this.MakeNoise();
		this.DefineYourself();
	}
});

// Declare named classes by Class.Define(...) call 
// into global memory space as 'Animal.Dog' and 'Animal.Cat'
// as extended classes from 'Animal' class.
Class.Define('Animal.Dog', {
	Extend: Animal,
	TellYourStory: function () {
		this.MakeNoise();
		this.IntroduceYourself();
		this.DefineYourself();
		console.log("But I'm the best friend of human.")
	}
});
Class.Define('Animal.Cat', {
	Extend: Animal,
	TellYourStory: function () {
		this.MakeNoise();
		this.IntroduceYourself();
		this.DefineYourself();
		console.log(
			"I don't care about people, but sometimes <br />"+
			"they have something very good to eat."
		);
	}
});

// Create instances (all ways are creating an instance):
var creature = Class.Create("Animal", "Creature", "Rrroooaaarrr!")
var dog = new Animal.Dog("Charlie", "Wrr haf!");
var cat = Animal.Cat.GetInstance('Suzy', 'Pchchchchch!');



// 'Rrroooaaarrr!'

// Globaly, I'm an 'Animal'.
// More precisely, I'm a 'Animal'.
// I belong to namespace ''.
// My full description is 'Animal'.
creature.TellYourStory();


console.log("-------------------");


// 'Wrr haf!'
// People call me 'Charlie'.

// Globaly, I'm an 'Animal'.
// More precisely, I'm a 'Dog'.
// I live between 'Animal'.
// My type is 'Animal.Dog'.

// But the best friend of human.
dog.TellYourStory();


console.log("-------------------");


// Pchchchchch! [String]
// People call me 'Suzy'. [String]

// Globaly, I'm an 'Animal'.
// More precisely, I'm a 'Cat'.
// I live between 'Animal'.
// My type is 'Animal.Cat'. [String]

// I don't care about people, but sometimes 
// they have something very good to eat.
cat.TellYourStory();


console.log("-------------------");

console.log(dog instanceof Animal); // true
console.log(dog instanceof Animal.Dog); // true
console.log(dog instanceof Animal.Cat); // false
console.log(dog instanceof Date); // false

console.log("-------------------");

console.log(dog.static.Name); // 'Dog'
console.log(dog.static.Fullname); // 'Animal.Dog'
console.log(dog.static.Namespace); // 'Animal'
console.log(dog.static.Extend.Name); // 'Animal'
console.log(dog.static.Extend.Fullname); // 'Animal'
console.log(dog.static.Extend.Namespace); // ''

console.log("-------------------");

console.log(dog.static === Animal.Dog); // true
console.log(dog.static.Extend === Animal); // true
console.log(dog.static.prototype === Animal.Dog.prototype); // true
console.log(dog.static.Extend.prototype === Animal.prototype); // true

console.log("-------------------");

console.log(typeof Animal.Dog); // 'function'
console.log(typeof dog); // 'object'
console.log(dog.toString()); // '[object Animal.Dog]'

4. Three Extended Classes With Static Members

Class.Define('Person', {
	Static: {
		Store: [],
		Count: 0,
		Register: function (person) {
			// in Static block:
			// - this context represents static context environment
			this.Store[person.id] = person;
			this.Count += 1;
		}
	},
	Constructor: function (id, name) {
		// in Constructor and dynamic methods:
		// - this context represents dynamic context environment
		this.id = id;
		this.name = name;
		this.self.Register(this);
	},
	id: 0,
	name: ''
});

Class.Define('Employe', {
	Extend: Person,
	Constructor: function (id, name, salary) {
		this.parent(id, name);
		this.salary = salary;
	},
	salary: 0,
	GetInfo: function () {
		return this.static.Name + " - name: " + this.name
			+ ", id: " + this.id + ", salary: " + this.salary;
	}
});

Class.Define('Manager', {
	Extend: Employe,
	Constructor: function (id, name, salary, idSecretary) {
		this.parent(id, name, salary);
		this.idSecretary = idSecretary;
	},
	idSecretary: 0,
	GetInfo: function () {
		var parentInfo = this.parent();
		return parentInfo + ",<br />"
			+ "&nbsp;&nbsp;&nbsp;" + "- secretary: "
			+ this.self.Store[this.idSecretary].GetInfo();
	}
});

// create class instance in standard way
var prManager = new Manager(0, 'Douglas Bridges', 50000, 1);

// create class instance by string as first argument, 
// all constructor params as second argument array
var secretary = Class.Create('Employe', 1, 'Janet Williams', 30000);

// 'Employe - name: Janet Williams, id: 1, salary: 30000'
console.log(secretary.GetInfo());

// 'Manager - name: Douglas Bridges, id: 0, salary: 50000,
// - secretary: Employe - name: Janet Williams, id: 1, salary: 30000'
console.log(prManager.GetInfo());

// Primitive values are not linked,
// so real count of registered persons
// is written in Person.Count memory space
console.log(Person.Count);	// 2
console.log(Employe.Count);	// 0
console.log(Manager.Count);	// 0

// Nonprimitive values are lined as references,
// so registered persons store is written 
// in Person.Count memory space and two another links are created
console.log(Person.Store.length);	// 2
console.log(Employe.Store.length);	// 2
console.log(Manager.Store.length);	// 2

5. Three Controller Classes And Different Behaviour In Actions

// System controller class - parent for all controllers:
Class.Define('Controller', {
	Static: {
		Dispatch: function (path, actionName) {
			new this.static(path)[actionName + 'Action']().Render();
		}
	},
	Constructor: function (path) {
		this.path = path;
	},
	path: null,
	Render: function () {
		console.log(JSON.stringify(this.path));
	}
});

// Front controller class - parent for all front controllers:
Class.Define('Controller.Front', {
	Extend: Controller,
	prepareView: function () {
		this.view = {
			path: this.path,
			agent: navigator.appName,
			lang: navigator.language
		};
	},
	view: null,
	Render: function () {
		console.log(
			JSON.stringify(this.view, null, "  ")
		);
	}
});

// Specific controller class for text pages,
// this controller will be dispatched 4 times:
Class.Define('Controller.Front.Default', {
	Extend: Controller.Front,
	prepareView: function () {
		this.parent(arguments);
		this.view.content = "You are here: '{0}'."
			.format(this.view.path.substr(1));
		this.view.layout = 'two-columns';
		this.view.leftMenu = [
			'About', 'Partners', 'Contacts'
		];
	},
	HomeAction: function () {
		/*****************************************************/
		/* You can call parent method directly from         **/
		/* any other method to skip current implementation! **/
		this.parent.prepareView();
		/*****************************************************/
		this.view.content = 'Welcome to our website!';
		this.view.layout = 'one-column';
		return this;
	},
	DefaultAction: function () {
		this.prepareView();
		return this;
	},
	ContactsAction: function () {
		this.prepareView();
		this.view.contactMain = 'info@company.com';
		return this;
	}
});


// Dispatching different requests to different 
// actions with different needs:

var ctrlDef = Controller.Front.Default;

ctrlDef.Dispatch('/home',		'Home');
ctrlDef.Dispatch('/about-us',	'Default');
ctrlDef.Dispatch('/partners',	'Default');
ctrlDef.Dispatch('/contacts',	'Contacts');

6. Class A, B, C And Parent Methods Calls Flows

Class.Define('A', {
	Static: {
		Create: function (one, two, three) {
			console.log(this.self.Name + '::Create(' + one + ',' + two + ',' + three + ')');
			return Class.Create(this.static.Name, arguments);
		},
		FirstStatic: function (a, b, c) {
			console.log(this.self.Name + '::FirstStatic(' + a + ',' + b + ',' + c + ')');
		}
	},
	Constructor: function (one, two, three) {
		console.log(this.self.Name+'->Constructor('+one+','+two+','+three+')');
	},
	FirstDynamic: function (f, g, h) {
		console.log(this.self.Name+'->FirstDynamic('+f+','+g+','+h+')');
		return this;
	},
	SecondDynamic: function (x, y, z) {
		console.log(this.self.Name+'->SecondDynamic('+x+','+y+','+z+')');
		return this;
	},
	ThirdDynamic: function (x, y, z) {
		console.log(this.self.Name+'->ThirdDynamic('+x+','+y+','+z+')');
		return this;
	}
});

Class.Define('B', {
	Extend: A,
	Static: {
		FirstStatic: function (a, b, c) {
			console.log("this is never called");
		},
		SecondStatic: function (a, b, c) {
			console.log(this.self.Name+'::SecondStatic('+a+','+b+','+c+')');
			this.parent.FirstStatic(a, b, c);
		}
	},
	Constructor: function (one, two, three) {
		console.log(this.self.Name+'->Constructor('+one+','+two+','+three+')');
		this.parent(arguments);
	},
	FirstDynamic: function (x, y, z) {
		console.log(this.self.Name+'->FirstDynamic('+x+','+y+','+z+')');
		this.ThirdDynamic(x, y, z);
		return this;
	},
	ThirdDynamic: function (x, y, z) {
		console.log(this.self.Name+'->ThirdDynamic('+x+','+y+','+z+')');
		this.parent.ThirdDynamic(x, y, z);
		return this;
	}
});

Class.Define('C', {
	Extend: B,
	Static: {
		SecondStatic: function (a, b, c) {
			console.log("this is never called");
		},
		ThirtStatic: function (a, b, c) {
			console.log(this.self.Name + '::ThirtStatic(' + a + ',' + b + ',' + c + ')');
			this.parent.SecondStatic(a, b, c);
		}
	},
	one: 0,
	two: 0,
	three: 0,
	Constructor: function (one, two, three) {
		this.one = one;
		this.two = two;
		this.three = three;
		console.log(this.self.Name+'->Constructor('+one+','+two+','+three+')');
		this.parent(arguments);
	},
	FirstDynamic: function (f, g, h) {
		console.log(this.self.Name+'->FirstDynamic('+f+','+g+','+h+')');
		this.parent.SecondDynamic(f, g, h);
		return this;
	},
	SecondDynamic: function (m, n, o) {
		console.log(this.self.Name+'->SecondDynamic('+m+','+n+','+o+')');
		this.ThirdDynamic(m, n, o);
		return this;
	},
	ThirdDynamic: function (x, y, z) {
		console.log(this.self.Name+'->ThirdDynamic('+x+','+y+','+z+')');
		this.parent.FirstDynamic(x, y, z);
		return this;
	}
});


/**
This code flows through methods:
	C::ThirtStatic(a,b,c)
		B::SecondStatic(a,b,c)
			A::FirstStatic(a,b,c)
	C::Create(1,2,3)
*/
C.ThirtStatic('a', 'b', 'c');


/**
This code flows through methods:
	C->Constructor(1,2,3)
		B->Constructor(1,2,3)
			A->Constructor(1,2,3)
*/
var c = C.Create(1, 2, 3)
	/**
	This code flows through methods:
		C->FirstDynamic(f,g,h)
				A->SecondDynamic(f,g,h)
	*/
	.FirstDynamic('f', 'g', 'h')
	/**
	This code flows through methods:
		C->SecondDynamic(m,n,o)
		C->ThirdDynamic(m,n,o)
			B->FirstDynamic(m,n,o)
			B->ThirdDynamic(m,n,o)
				A->FirstDynamic(m,n,o)
	*/
	.SecondDynamic('m', 'n', 'o')
	/**
	This code flows through methods:
		C->ThirdDynamic(x,y,z)
			B->FirstDynamic(x,y,z)
				A->ThirdDynamic(x,y,z)
	*/
	.ThirdDynamic('x', 'y', 'z');

console.log(c.toString()); // [object C]

7. Syntax Customization

// syntax customization at app start:
Class.define = Class.Define;
Class.create = Class.Create;
Class.getByName = Class.GetByName;
Class.CustomizeSyntax({
	GetClassUid		: 'getClassUid',
	GetInstanceUid	: 'getInstanceUid',
    Inherited		: 'inherited',
	Extend			: 'extend',
	Static			: 'static',
	// for 'constructor' is not possible to use javascript 
	// build in function property 'constructor', use different:
	Constructor: 'construct',
	// for 'name' is not possible to use javascript 
	// build in 'Function.name' property, use different:
	Name			: 'className',
	Fullname		: 'classFullname',
	Namespace		: 'classNamespace',
	static			: 'static',
	self			: 'self',
	parent			: 'parent'
});


// Declare named class by Class.Define(...) 
// call into global memory space as 'Animal'
Class.define('Animal', {
	static: {
		getInstance: function () {
			// this.static contains a child class definition
			// as later static binding in PHP normaly works
			return new this.static(arguments);
		}
	},
	construct: function (name, sound) {
		this.name = name;
		this.sound = sound;
	},
	name: '',
	sound: '',
	makeNoise: function () {
		console.log(this.sound);
	},
	introduceYourself: function () {
		console.log(
			"People call me '{0}'.".format(this.name)
		);
	},
	defineYourself: function () {
		console.log(
			"Globaly, I'm an '{0}'.".format(this.self.className)
			+ '<br />' +
			"More precisely, I'm a '{0}'.".format(this.static.className)
			+ '<br />' +
			"I belong to namespace '{0}'.".format(this.static.classNamespace)
			+ '<br />' +
			"My full description is '{0}'.".format(this.static.classFullname)
		);
	},
	tellYourStory: function () {
		this.makeNoise();
		this.defineYourself();
	}
});

// Declare named classes by Class.Define(...) call 
// into global memory space as 'Animal.Dog' and 'Animal.Cat'
// as extended classes from 'Animal' class.
Class.define('Animal.Dog', {
	extend: Animal,
	tellYourStory: function () {
		this.makeNoise();
		this.introduceYourself();
		this.defineYourself();
		console.log("But I'm the best friend of human.")
	}
});
Class.define('Animal.Cat', {
	extend: Animal,
	tellYourStory: function () {
		this.makeNoise();
		this.introduceYourself();
		this.defineYourself();
		console.log(
			"I don't care about people, but sometimes <br />" +
			"they have something very good to eat."
		);
	}
});

// Create instances:
var creature = Class.create("Animal", "Creature", "Rrroooaaarrr!")
var dog = new Animal.Dog("Charlie", "Wrr haf!");
var cat = Animal.Cat.getInstance('Suzy', 'Pchchchchch!');



// 'Rrroooaaarrr!'

// Globaly, I'm an 'Animal'.
// More precisely, I'm a 'Animal'.
// I belong to namespace ''.
// My full description is 'Animal'.
creature.tellYourStory();


console.log("-------------------");

// 'Wrr haf!'
// People call me 'Charlie'.

// Globaly, I'm an 'Animal'.
// More precisely, I'm a 'Dog'.
// I live between 'Animal'.
// My type is 'Animal.Dog'.

// But the best friend of human.
dog.tellYourStory();


console.log("-------------------");


// Pchchchchch! [String]
// People call me 'Suzy'. [String]

// Globaly, I'm an 'Animal'.
// More precisely, I'm a 'Cat'.
// I live between 'Animal'.
// My type is 'Animal.Cat'. [String]

// I don't care about people, but sometimes 
// they have something very good to eat.
cat.tellYourStory();



console.log("-------------------");

console.log(dog instanceof Animal); // true
console.log(dog instanceof Animal.Dog); // true
console.log(dog instanceof Animal.Cat); // false
console.log(dog instanceof Date); // false

console.log("-------------------");

console.log(dog.static.className); // 'Dog'
console.log(dog.static.classFullname); // 'Animal.Dog'
console.log(dog.static.classNamespace); // 'Animal'
console.log(dog.static.extend.className); // 'Animal'
console.log(dog.static.extend.classFullname); // 'Animal'
console.log(dog.static.extend.classNamespace); // ''

console.log("-------------------");

console.log(dog.static === Animal.Dog); // true
console.log(dog.static.extend === Animal); // true
console.log(dog.static.prototype === Animal.Dog.prototype); // true
console.log(dog.static.extend.prototype === Animal.prototype); // true

console.log("-------------------");

console.log(typeof Animal.Dog); // 'function'
console.log(typeof dog); // 'object'
console.log(dog.toString()); // '[object Animal.Dog]'

Browser Usage

  • install any browser if necessary (MSIE6+, Firefox, Google Chrome, Safari, Opera...)
  • create new empty text file with name "example.html":
  • open the file "example.html" in the browser to run
<!DOCTYPE HTML>
<html lang="en-US">
	<head>
		<meta charset="UTF-8" />
	</head>
	<body>
		<script src="./class.dev.js" type="text/javascript"></script>
		<script type="text/javascript">
			var MyClass = Class({
				Constructor: function () {
					console.log("It works!");
				}
			});
			var myInstance = new MyClass(); // "It works!
		</script>	
	</body>
</html>

Node.js Usage

  • install node.js from nodejs.org if necessary
  • create new empty text file with name "example.js":
  • type into command line window "node example.js" to run
require('class-advanced');
var MyClass = Class({
	Constructor: function () {
		console.log("It works!");
	}
});
var myInstance = new MyClass(); // "It works!

Windows Script Host Usage

  • create new empty text file with name "example.wsf":
  • doubleclick on the file "example.wsf" to run
<job>
	<script type="JScript" src="./class.dev.js"></script>
	<script type="JScript">
		var MyClass = Class({
			Constructor: function () {
				WScript.echo("It works!");
			}
		});
		var myInstance = new MyClass(); // "It works!
	</script>
</job>

DEMOS

Keywords

FAQs

Last updated on 14 Aug 2017

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc