Skip to content

Instantly share code, notes, and snippets.

@zgangx
Last active September 16, 2020 18:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zgangx/102aed0eab753c80ec8bfcd8511f414e to your computer and use it in GitHub Desktop.
Save zgangx/102aed0eab753c80ec8bfcd8511f414e to your computer and use it in GitHub Desktop.
javascript class emulation
//if you call contructor function without new prefix.
//function return undefined and create a global variable name
//window.name = 'bob'
// new prefix is creae a new empty context and switches from global
// to current instance.
//By default, if you don’t return anything from a constructor function
//this—the current context—will be returned.
//Otherwise, you can return any nonprimitive type.
//For example, we could return a function that would set up a new class
//class emulation
var Class = function(){
var klass = function(){
this.init.apply(this, arguments);
};
klass.prototype.init = function(){};
return klass;
};
var Person = new Class;
Person.prototype.init = function(name){
this.name = name;
};
// Usage:
var person = new Person;
//Adding class function: static function added directly on the class
Person.find = function(id){};
//class function usage
var person = Person.find(1);
//Adding instance function
Person.prototype.breath = function(){}
//instance function usage
var person = new Person;
person.breath();
//Common pattern is to alias a class'prototype to fn which less verbose
//example of jQuery plug-ins jQuery.fn
Person.fn = Person.prototype;
Person.fn.run = function(){}
//different way to add class function and instance function of adding extend() and include()
//compare with class emulation we build at start
var Class = function(){
var klass = function(){
this.init.apply(this, arguments);
};
klass.prototype.init = function(){};
// Shortcut to access prototype
klass.fn = klass.prototype;
// Shortcut to access class
klass.fn.parent = klass;
// Adding class properties: adding an extend() function which accepts an obj.
// obj are iterated and copied directly onto class
klass.extend = function(obj){
var extended = obj.extended;
for(var i in obj){
klass[i] = obj[i];
}
if (extended) extended(klass)
};
// Adding instance properties: adding an include() function which accepts an obj.
// obj are iterated and copied directly onto class prototype
klass.include = function(obj){
var included = obj.included;
for(var i in obj){
klass.fn[i] = obj[i];
}
if (included) included(klass)
};
return klass;
}
//ussage add class function
var Person = new Class;
Person.extend({
find: function(id) { /* ... */ },
exists: functions(id) { /* ... */ }
});
var person = Person.find(1);
//ussage add instance function
Person.include({
save: function(id) { /* ... */ },
destroy: functions(id) { /* ... */ }
});
var person = new Person;
person.save();
//also implementing support for extended and included callbacks.
//If these properties are present on the passed object, they’ll be invoked:
Person.extend({
extended: function(klass) {
console.log(klass, " was extended!");
}
});
//The Beauty of of this approach is we not got support for modules.
//Modules are reusable piece of code and can be used as an alternative to
//inheritance for sharing common properties among classes
var ORMModule = {
save: function(){}
}
var Person = new Class
var Asset = new Class
Person.include(ORMModule);
Asset.include(ORMModule);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment