Last active
September 16, 2020 18:03
-
-
Save zgangx/102aed0eab753c80ec8bfcd8511f414e to your computer and use it in GitHub Desktop.
javascript class emulation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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