You know the old mantra: eval is evil! Well, maybe, but I hate writing
lots of code, and I like my debugging to be simple. I wanted to write a
shorter way to extend a parent class into a child class. Long way (too
much repeated code/risk of copy & paste errors):
Long winded: manually creating each class from scratch
1234567891011121314151617181920212223
// Root classfunctionMyClass(){returnthis;}// Create first subclassfunctionMyChildClass1(){returnthis;}MyChildClass1.prototype=newMyClass();MyChildClass1.prototype.parent=MyClass.prototype;MyChildClass1.prototype.constructor=MyChildClass1;// Create second subclassfunctionMyChildClass2(){returnthis;}MyChildClass2.prototype=newMyClass();MyChildClass2.prototype.parent=MyClass.prototype;MyChildClass2.prototype.constructor=MyChildClass2;// Create an instancevarinstance=newMyChildClass2();
Shorter way (gives wrong output on console.log()):
Shorter, but class names are console.log’d incorrectly
12345678910111213141516171819202122
// Automation functionfunctionNS_Extend(parentClass,childClassName){varchildClass=function(){returnthis;}childClass.prototype=newparentClass();childClass.prototype.parent=parentClass.prototype;childClass.prototype.constructor=childClass;window[childClassName]=childClass;}// Root ClassfunctionMyClass(){returnthis;}// First subclassNS_Extend(MyClass,'MyChildClass1');// Second subclassNS_Extend(MyClass,'MyChildClass2');// Create an instancevarinstance=newMyChildClass2();
Simple, but when I console.log(instance) it gives me
NS_Extend.childClass as the name of the class, rather than
MyChildClass2 as was done previously. It makes no difference to the
functionality of the app, but it makes my debugging a bit harder. And I
really don’t want to have to keep defining
function ClassName(){return this;} everywhere - waste of time typing
all that repeated code! So I figured I’d define the function through
eval(). However that didn’t work, until I realised that eval() is
scoped to the current context. So to define a window level function we’d
need to change the scope to the window object. Easy enough with
JavaScript’s .call() method. The solution:
Eval isn’t always evil: Fixing the console.log class names.