Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>In my framework, everything is an object or an "interface".</p> <p>Interfaces define the common functions (methods / property_gets / property_sets) that objects may have.</p> <p>You create an interface like this: <code>var some_interface = GetInterface(constructor, interface_setup, parent_interface..)</code></p> <p>You can specify any number of parent_interfaces. So if <code>interface_A</code> inherits both <code>interface_B</code> and <code>interface_C</code>, you can create interface_A as such: <code>GetInterface(constructor, interface_setup, interface_B, interface_C);</code></p> <p>If <code>interface_A</code> inherits <code>interface_X</code> and <code>interface_X</code> inherits <code>interface_Y</code>, then <code>interface_A</code> will have all the functions which both <code>interface_X</code> and <code>interface_Y</code> has.</p> <p>Interfaces which do not require a constructor will leave the constructor argument as null. The interface_setup is a function which looks like this:</p> <pre><code>function(proto){ } </code></pre> <p>The object that the <em>proto</em> argument points to has 4 methods: <code>SetM</code>, <code>ShadowM</code>, <code>SetP</code>, and <code>ShadowP</code>.</p> <p>You use these 4 methods to <em>setup</em> your interface.</p> <p>This framework also provides lazy instantiation of interfaces. (in other words the setup code will never actually be ran until it is actually first needed).</p> <p>Limitations of this framework requires at least support for <code>Object.keys</code>, <code>Object.getOwnPropertyDescriptor</code> and <code>Object.defineProperty</code>. (In other words it works in the latest versions of FireFox, IE, Chrome, Safari but not Opera)</p> <p><strong>TestPage2.html:</strong></p> <pre><code>&lt;!doctype html&gt; &lt;script src="js.js"&gt;&lt;/script&gt; &lt;script&gt; var human = GetInterface(function(){ },function(proto){ //alert("trace: initing human"); proto.$SetM("Sleep",function(){ alert(this.Name+" is sleeping"); }); proto.$SetP("Name",function(){ return this._name; },function(value){ this._name=value; }); }); var female = GetInterface(function(){ },function(proto){ //alert("trace: initing female"); proto.$SetM("Dance",function(){ alert(this.Name+" is dancing"); }); },human); var male = GetInterface(function(){ },function(proto){ //alert("trace: initing male"); proto.$SetM("Fight",function(){ alert(this.Name+" is fighting"); }); proto.$ShadowP("Name",function(parent_get){ return "Mr. "+parent_get(); },function(parent_set,value){ parent_set(value); }); },human); var child = GetInterface(function(){ },function(proto){ //alert("trace: initing child"); proto.$SetM("Play",function(){ alert(this.Name+" is playing"); }); },human); var adult = GetInterface(function(){ },function(proto){ //alert("trace: initing adult"); proto.$SetM("Work",function(){ alert(this.Name+" is working"); }); },human); var mammal = GetInterface(function(){ },function(proto){ //alert("trace: initing mammal"); proto.$SetM("DoMammalStuff",function(){ alert("doing mammal stuff"); }); }); var john=new male(); john.Name="john"; john.Sleep(); var mary=new female(); mary.$IsA(child); mary.$IsA(mammal); mary.$Setup(function(proto){ proto.$ShadowP("Name",function(parent_get){ return "Miss "+parent_get.call(this); },function(parent_set,value){ parent_set.call(this,value); }); }); mary.Name="mary"; mary.Play(); &lt;/script&gt; </code></pre> <p><strong>TestPage.html:</strong></p> <pre><code> &lt;!doctype html&gt; &lt;script src="js.js"&gt;&lt;/script&gt; &lt;script&gt; var human_interface = GetInterface(function(){ },function(proto){ alert("trace: initing human"); proto.$SetM("Sleep",function(){ alert(this.Name+" is sleeping"); }); proto.$SetP("Name",function(){ return this._name; },function(value){ this._name=value; }); }); var female_interface = GetInterface(function(){ },function(proto){ alert("trace: initing female"); proto.$SetM("Dance",function(){ alert(this.Name+" is dancing"); }); },human_interface); var male_interface = GetInterface(function(){ },function(proto){ alert("trace: initing male"); proto.$SetM("Fight",function(){ alert(this.Name+" is fighting"); }); },human_interface); var child_interface = GetInterface(function(){ },function(proto){ alert("trace: initing child"); proto.$SetM("Play",function(){ alert(this.Name+" is playing"); }); },human_interface); var adult_interface = GetInterface(function(){ },function(proto){ alert("trace: initing adult"); proto.$SetM("Work",function(){ alert(this.Name+" is working"); }); },human_interface); var mammal_interface = GetInterface(function(){ },function(proto){ alert("trace: initing mammal"); proto.$SetM("DoMammalStuff",function(){ alert("doing mammal stuff"); }); }); var john={}; john.$IsA(adult_interface); //the above 2 lines are equal to simply doing: //var john=new adult_interface(); //you can think of it as a shortcut john.$IsA(mammal_interface); john.DoMammalStuff(); john.Name="john"; john.Sleep(); var mary=new female_interface(); mary.$IsA(child_interface); mary.$IsA(mammal_interface); mary.DoMammalStuff(); mary.Name="mary"; mary.Play(); mary.Dance(); &lt;/script&gt; </code></pre> <p><strong>Js.js:</strong></p> <pre><code>"use strict"; var GetInterface; (function(){ //================================================================================// //(constructor:Function, setup:Function?, parent_interfaces:Function..):Function GetInterface = function (constructor, setup) { var parent_classes = GetParray(arguments, 2); var output = function () { output.$Init(); for (var x = parent_classes.length - 1; x &gt;= 0; --x) { parent_classes[x](this); } if(constructor===null){ constructor.apply(this, arguments); } }; output.$Init = Mize(function () { var output_proto = output.prototype; parent_classes.forEach(function (parent_class) { parent_class.$Init(); Infect(output_proto, parent_class.prototype); }); init_proto(output_proto,setup); if(setup!==undefined){ setup(output_proto); } }); return output; }; var init_proto=function(proto){ $defineProperty(proto, "$SetM", { value: set_m, writable: true, configurable: true }); $defineProperty(proto, "$ShadowM", { value: shadow_m, writable: true, configurable: true }); $defineProperty(proto, "$SetP", { value: set_p, writable: true, configurable: true }); $defineProperty(proto, "$ShadowP", { value: shadow_p, writable: true, configurable: true }); }; var set_m = function (method_name, method) { this[method_name] = method; }; var set_p = function (property_name, getter, setter) { $defineProperty(this, property_name, { get: getter, set: setter, enumerable: true, configurable: true }); }; var shadow_m = function (method_name, supplied_method) { var old_method = this[method_name]; this[method_name] = function () { var args = GetParray(arguments); args.unshift(old_method.bind(this)); supplied_method.apply(this, args); }; }; var shadow_p = function (property_name, getter, setter) { var old_descriptor = $getOwnPropertyDescriptor(this, property_name); var old_get = old_descriptor.get; var old_set = old_descriptor.set; $defineProperty(this, property_name, { get: function () { return getter.call(this, old_get.bind(this)); }, set: function (value) { setter.call(this, old_set.bind(this), value); }, enumerable: true, configurable: true }); }; var $slice=Array.prototype.slice; var $defineProperty=Object.defineProperty; var $getOwnPropertyDescriptor=Object.getOwnPropertyDescriptor; if($defineProperty===undefined){ throw "Object.defineProperty, Object.getOwnPropertyDescriptor, Object.keys are required"; } //================================================================================// //(victim:Object, disease:Object):void var Infect=function (victim, disease, excludes) { var keys=Object.keys(disease); if(excludes!==undefined){ excludes.forEach(function(exclude){ ForEach(keys,function(key,x){ if(key===exclude){ keys.splice(x,1); return false; } }); }); } keys.forEach(function(key){ $defineProperty(victim, key, $getOwnPropertyDescriptor(disease, key)); }); }; //================================================================================// //(args:Object # arguments object #, start_index:int?):Array var GetParray = function (args, start_index) { if (start_index === undefined) { start_index = 0; } return $slice.call(args, start_index); }; //================================================================================// //(array:Array, f:Function(item:Object|null, index:pint):boolean?):Object var ForEach=function(array,f){ for (var x = 0, xx = array.length, last_index=xx-1; x &lt; xx; ++x) { var result = f(array[x], x, last_index); if (result !== undefined) { return result; } } }; //================================================================================// //provides memoization. //(f:Function, arity_fixed:boolean?true):Function //caching is done according to the inputs. the results of calling function(undefined) and function() are cached differently. //if arity is fixed, optimizations can be done var Mize=function(f, arity_fixed) { if (arity_fixed === undefined) { arity_fixed = true; } var used; //for 0 arg var result; //for 0 arg var results; //for &gt;0 args var used_params; //for 1 arg var used_param_sets; //for &gt;1 args var f_length = f.length; var use_generic = !arity_fixed || f_length &gt; 3; if (use_generic) { //if `f_length` &lt;= 3, it will be optimized (i.e. not using generic function) results = []; used_param_sets = []; return function () { var params = GetParray(arguments); var result_found = false; var result = ForEach(used_param_sets,function (used_param_set, x) { if (used_param_set.length === params.length) { var params_match = true; ForEach(params,function (param, y) { if (used_param_set[y] !== param) { params_match = false; return false; } }); if (params_match) { result_found = true; return results[x]; } } }); if (!result_found) { used_param_sets.push(params); result = f.apply(null, params); results.push(result); } return result; }; } if (f_length === 0) { used = false; return function () { if (!used) { result = f(); used = true; } return result; }; } if (f_length === 1) { used_params = []; } else { used_param_sets = []; } results = []; switch (f_length) { case 1: return function (arg) { var result_found = false; var result = ForEach(used_params,function (used_param, x) { if (arg === used_param) { result_found = true; return results[x]; } }); if (!result_found) { used_params.push(arg); result = f(arg); results.push(result); } return result; }; break; case 2: return function (arg1, arg2) { var result_found = false; var result = ForEach(used_param_sets,function (used_param_set, x) { if (arg1 === used_param_set[0] &amp;&amp; arg2 === used_param_set[1]) { result_found = true; return results[x]; } }); if (!result_found) { used_param_sets.push([arg1, arg2]); result = f(arg1, arg2); results.push(result); } return result; }; break; case 3: return function (arg1, arg2, arg3) { var result_found = false; var result = ForEach(used_param_sets,function (used_param_set, x) { if (arg1 === used_param_set[0] &amp;&amp; arg2 === used_param_set[1] &amp;&amp; arg3 === used_param_set[2]) { result_found = true; return results[x]; } }); if (!result_found) { used_param_sets.push([arg1, arg2, arg3]); result = f(arg1, arg2, arg3); results.push(result); } return result; }; break; default: throw "Invalid `f_length`: " + f_length; } }; //================================================================================// Object.prototype.$Setup=function(setup){ setup(Object.getPrototypeOf(this)); }; //================================================================================// Object.prototype.$IsA=function(_interface){ var excludes=GetParray(arguments,1); if(this.$SetM===undefined){ this.$SetM=set_m; this.$SetP=set_p; this.$ShadowM=shadow_m; this.$ShadowP=shadow_p; } _interface.$Init(); /*var this_proto={}; init_proto(this_proto); Infect(this_proto,Object.getPrototypeOf(this)); this.__proto__=this_proto;*/ Infect(Object.getPrototypeOf(this),_interface.prototype,excludes); }; //================================================================================// })(); </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload