Javascript prototype’s makes me crying

Prototype

Yes many times I cried because of prototype pattern when ever I tried to understand about it. May be I’m came from another scripting language(ActionScript3) background with Class oriented language. Anyhow after read many times about Prototype my reaction will be😦

We are really exciting about es6 right. we have lot of stunning features like arrows, classes, enhanced object literals,template strings, let + const, iterators + for..of, generators, modules and many more wow feature in es6.Then why do we care about prototype matter even though we have Class feature in es6(atleast future) it purely rely on prototype pattern. In other words prototype pattern powered to class mechanism in es6. JavaScript remains prototype-based and one of reason behind this prototype pattern is more powerful than classical inheritance which is coming from static language like Java, C# etc…,

Let’s discuss about why prototype pattern is important in javascript. why do we need to care about prototype? Where it’s play critical role. Let’s thing about prototype.

Going to define simple constructor function to hold the point of x,y number purpose of draw shapes in canvas.

Let’s define Point constructor to hold x and y points to represents position of Shape.

Constructor Function

function Point(x,y){
this.x = x;
this.y = y;</pre>
this.getPoint = function(){
return { x:x, y:y };
}
this.toString = function(){
console.log("x : "+x + " y : "+y);
}
}

We need Point constructor to draw a line. But above code have one disadvantage of Point constructor function and it’s own constructor pattern problem.

var p1 = new Point(100,100);
var p2 = new Point(100,100);
var p3 = new Point(100,100);

Now examine construtor function. Let’s do simple comparison with p1 and p2.</pre>
</pre>
p1.constructor === p2.constructor
> true

Any number of instance create by Point construtor function it is always points to Point.So what is the issue here. Wait look at 2 methods and 2 props on Point constructor function. These are own property of p1 and p2. Meaning, for each instance of Point having their own props and method this is cons of constructor function as well. Since there is no options to share properties and methods among their instance.

Let’s see practically what is the problem with construtor function.

> p1.getPoint === p2.getPoint
false

Above statement is clearly stated that p1 having getPoint their own funtion and p2 having getPoint their own function so completly unccesseary of creating getPoint() and toString() function for each instance of Point.

That’s where the prototype come into the picture and it played nicely. Now redefine the above Point constructor function with the help of prototype

function Point(x,y){
this.x = x;
this.y = y;
}

Point.prototype.getPoint = function(){
return { x:x, y:y };
}

Point.prototype.toString = function(){
console.log(“x : “+x + ” y : “+y);
}
> p1.getPoint === p2.getPoint
> true

So Prototype is able to sharing properties and method among their instances. Here are we removed 2 methods from Point function atleast own methods. Also removed methods are attached into prototype object. Do you know Prototype object where it is come from ?

Prototype is simple plain object which will create every time when object instanitate with ‘new’ keyword. By default it always points to Object.prototype.

function Point(x,y){
this.x = x;
this.y = y;
}
> var p1 = new Point(100,100);
> console.log(p1.tostring());

toString() is not defined on Point constructor function then how it is print out “[object Object]”. Because of all javascript object link to ‘Object’ prototype. Object prototype having toString(), valueOf, hasOwnProperty() and so on.

The reason behind this invoking a function as a constructor (i.e. with the new keyword) runs the following steps:

Create a new object

Set the prototype of that object to the object in the prototype property of the function

Execute the constructor function in the context of that object (i.e. this is the new object)

Return that object (if the constructor has no return statement)

If you understood #2 you will come to know toString() method where it is comes from. Let’s see how prototype will supports inheritance with lot of flaws and by the time will correct it.

Inheritance

In javascript inheritance is implemented through a special property __proto__ (named [[Prototype]] in the specification. It is just one approach there are many way to acheive reusablity this manner.

function Shape(){
this.props = {name:’Shape’};
}

function Square(){
}

Square.prototype = new Shape();

var s1 = new Square();
var s2 = new Square();

console.log(s1.props.name);
console.log(s2.props.name);
> s1.props.name
“Shape”
> s1.props.name = “I’m Square”
“I’m Square”
> s2.props.name
“I’m Square”

Problem #1 : All reference type in parent will reflect changes to child object. Square.prototype = new Shape(); become as Square.prototype.props then finally it share ‘props’ perperties with all instance of Square.

Problem #2 : Square.prototype = new Shape(); no way to pass parameters to Shape function(atleast at this point of time)

So let’s solve the above problem #2 with the help of borrow constructor pattern.

function Shape(){
this.props = {name:’Shape’};
}

function Square(){
Shape.apply(this,arguments); //This line solve above two problem
}

Square.prototype = new Shape();

var s1 = new Square();
var s2 = new Square();

console.log(s1.props.name);
console.log(s2.props.name);
> s1.props.name = “I’m square instance”
“I’m square instance”
> s2.props.name
“Shape”
Now clearly stated that 2 instance having their own properties regardless of primities or reference type. Is it fine ohh wait one more issue with above code. what is the issue now. Constructor function is called twice ie,Square.prototype = new Shape(); and Shape.apply(this,arguments); both called construtctor function each time this shows clearly ineffecitent method. But don’t worry about luckly we have option to solve the problems too.

function Shape(){
console.log(‘Shape constructor called’);
this.props = {name:’Shape’};
}

function Square(){
Shape.apply(this,arguments); //This line solve above two problems
}

Square.prototype = new Shape();

var s1 = new Square();
var s2 = new Square();

console.log(s1.props.name);
console.log(s2.props.name);
> Shape constructor called
> Shape constructor called
> Shape constructor called

> s1.props.name = “I’m square instance”
“I’m square instance”
> s2.props.name
“Shape”

How do we solve the problem instead of creating new instance of Shape. Do assign the prototype of Shape Object.

function Shape(){
console.log(‘Shape constructor called’);
this.props = {name:’Shape’};
}

function Square(){
Shape.apply(this,arguments);
}

Square.prototype = Shape.prototype; //This line solve the constructor called twice.Share the parent prototype alone instead of instance properties and methods

var s1 = new Square();
var s2 = new Square();
> Shape constructor called
> Shape constructor called
Ohh this time only once constructor function is being called.

Let’s examine

> s1.constructor
function Shape()
Why it is points to Shape construtor function it should points to Square right. what went wrongs ? Take a look at

Square.prototype = Shape.prototype;
Square protype is completely replace with Shape.prototype so constructor properties in prototype also override. So don’t rely on construtor property. When ever protoptype obhect changes that time reset the constructor propery as well.

Square.prototype = Shape.prototype;
Square.prototype.constructor = Square;
Now it will points to Square instead of Shape. Instead of rely on constructor property on prototype. How ever ‘instance of’ operator does job well even without resetting the constructor property.

> s1 instanceof Square
true
> s1 instanceof Shape
true
> s1 instanceof Object
true
Find the below complete prototype pattern snippets with inheritance usage.

function Point(x,y){
this.x = x;
this.y = y;
}

function Shape(elem, points){
this.lines = [];
this.points = points || [];
this.elem = elem;
this.init();
}

Shape.prototype = {
constructor:Shape,
init:function(){
this.context = this.context || document.getElementById(this.elem).getContext(‘2d’);
},
draw:function(){
var ctx = this.context;
ctx.fillStyle = ‘green’;
ctx.beginPath();

ctx.moveTo(this.points[0].x,this.points[0].y);
for (var idx = 1; idx < this.points.length; idx++) {
ctx.lineTo(this.points[idx].x,this.points[idx].y);ctx.fill();
}

ctx.stroke();
ctx.closePath();
}
};

function extend(Child, Parent){
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
}

function Square(elem, points){
Shape.apply(this, arguments);
}

extend(Square,Shape);
// Square.prototype = Object.create(Shape.prototype);
// Square.prototype.constructor = Square;

var p1 = new Point(100,100);
var p2 = new Point(200,100);
var p3 = new Point(200,200);
var p4 = new Point(100,200);

var shape1 = new Shape(‘canvas’,[p1,p2,p3,p4]);
shape1.draw();
Also Shape function can be used to create many geometrical objects like Rectangle,Triangle and circle etc. Here circle is bit different behaviour which have to override ‘draw’ method in order to get desired output.

Finally:

🙂

Setting dynamic controller for directives in AngularJS

Working Demo in JSFiddle

Source : Checkout my answer in Stack OverFlow

HTML Markup

<communicator controller-name="PhoneCtrl" ></communicator>
<communicator controller-name="LandlineCtrl" ></communicator>

My AngularJS code look like,


var app = angular.module('myApp',[]).
directive('communicator', function(){
return {
    restrict : 'E',
    scope:{},
    controller : "@",
    name:"controllerName", 
    template:"<input type='text' ng-model='message'/><input type='button' value='Send Message' ng-click='sendMsg()'><br/>"          
  }   
}).
controller("PhoneCtrl",function($scope){
 $scope.sendMsg = function(){
     alert( $scope.message + " : sending message via Phone Ctrl");
    }
}).
controller("LandlineCtrl",function($scope){
    $scope.sendMsg = function(){
        alert( $scope.message + " : sending message via Land Line Ctrl ");
    }
})

Fake Enums in AS3


package
{
	final public class TargetPlatform
	{
		public static const APPLE_IPA:TargetPlatform = new TargetPlatform("ipa");
		public static const ANDROID_APK:TargetPlatform = new TargetPlatform("apk");
		public static const WINDOWS_AIR:TargetPlatform = new TargetPlatform("air");
		
		private var _value:String;
		
		public function TargetPlatform(value:String)
		{
			_value = value;
		}
		
		public function toString():String
		{
			return _value;
		}	
	}
}

How to build .air file through Adt.jar with the help of NativeProcess in Adobe AIR?


This class might helpful for you
air_command.bat
java -jar adt.jar -package -storetype pkcs12 -keystore  keyfile.p12 -storepass mypassword SampleApp.air SampleApp-app.xml SampleApp.swf

Before run applications

* make sure java class path is set
* <supportedProfiles>desktop extendedDesktop mobileDevice exendedMobileDevice</supportedProfiles>

to

<supportedProfiles>extendedDesktop</supportedProfiles></pre>
package
{
 import flash.desktop.NativeProcess;
 import flash.desktop.NativeProcessStartupInfo;
 import flash.events.ProgressEvent;
 import flash.filesystem.File;

 import mx.controls.Alert;

 public class PlatformPackaging
 {
 private var nativeProcess:NativeProcess;
 private var isErrorOccured:Boolean;

 private var batFile:File;
 private var cmdFile:File;

 private function get isWindows():Boolean
 {
 return true;
 }

 public function PlatformPackaging()
 {
 }

 public function start(targetPlatform:String):void
 {
 if(isWindows)
 {
 if(targetPlatform == TargetPlatform.APPLE_IPA)
 {
 batFile = File.applicationDirectory.resolvePath("publish/ipa_command.bat");
 cmdFile = new File("c:\\Windows\\System32\\cmd.exe");
 }
 else if(targetPlatform == TargetPlatform.WINDOWS_AIR)
 {
 batFile = File.applicationDirectory.resolvePath("publish/air_command.bat");
 cmdFile = new File("c:\\Windows\\System32\\cmd.exe");
 }
 else if(targetPlatform == TargetPlatform.ANDROID_APK)
 {
 batFile = File.applicationDirectory.resolvePath("publish/apk_command.bat");
 cmdFile = new File("c:\\Windows\\System32\\cmd.exe");
 }
 }

 proceedToPackaging();

 }

 private function proceedToPackaging():void {

 var processArgs:Vector.<String> = new Vector.<String>;

 processArgs.push("/c");
 processArgs.push(batFile.nativePath);

 var workingDirectory:File = File.applicationDirectory.resolvePath("publish/");
 var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();

 nativeProcessStartupInfo.arguments = processArgs;
 nativeProcessStartupInfo.executable = cmdFile;
 nativeProcessStartupInfo.workingDirectory = workingDirectory;

 nativeProcess = new NativeProcess();
 nativeProcess.addEventListener(ProgressEvent.STANDARD_ERROR_DATA,onStandardErrorOutputDataHandler);
 nativeProcess.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA,onStandardOutputDataHandler);
 nativeProcess.start(nativeProcessStartupInfo);
 }

 private function onStandardErrorOutputDataHandler(event:ProgressEvent) : void
 {
 var certResponse:String = nativeProcess.standardError.readUTFBytes(nativeProcess.standardError.bytesAvailable);

 trace(certResponse);

 isErrorOccured = true;

 if ( certResponse.substr(0,5) == "valid") {
 trace("Correct password!");
 nativeProcess.removeEventListener(ProgressEvent.STANDARD_ERROR_DATA,onStandardOutputDataHandler);
 nativeProcess.exit();
 } else {
 trace("Incorrect password! Error...");
 nativeProcess.removeEventListener(ProgressEvent.STANDARD_ERROR_DATA,onStandardOutputDataHandler);
 nativeProcess.exit();
 }

 Alert.show(certResponse,'Error');
 }

 protected function onStandardOutputDataHandler(event:ProgressEvent):void
 {
 var status:String = nativeProcess.standardOutput.readUTFBytes(nativeProcess.standardOutput.bytesAvailable);

 if(isErrorOccured == false)
 Alert.show(status)
 }
 }