Friday, June 1, 2012

JavaScript For C# Developers

No reason for a C# developer not to appreciate JavaScript. For more .NET like goodies in JavaScript, see my library fjs.lib.



Creating An Object (Object Literal)


C#
public class AClass {    

    static void Main() {

        var p = new AClass();
    }
}


JavaScript
 var p = { }; 


Creating An Object (Function Constructor)


C#
public class AClass {    

    static void Main() {

        var p = new AClass();
    }
}


JavaScript
function AClass() {

}
var p = new AClass();


Creating An Object (Object Literal II)


  • Anonymous Type vs Object Literal

C#
 var p = new { LastName = "Doe" };
    

JavaScript
 var p = { LastName : "Doe" };


Object With Properties And Methods (Object Literal)


C#
public class Person {

    public string LastName { get; set; }

    public Person(string lastName) {

        this.LastName = lastName;
    }
    public void Run() {

        Console.WriteLine(this.LastName + " is running...");
    }
    static void Main() {

        var p = new Person("Doe");
        p.Run(); 
    }
}

JavaScript
var p = {
     LastName : "Doe",
     run      : function() {

                        print(this.LastName + " is running..."); 
                   }
        };

p.run();


Object With Properties And Methods (Function Constructor)


C#
public class Person {

    public string LastName { get; set; }

    public Person(string lastName) {

        this.LastName = lastName;
    }
    public void Run() {

        Console.WriteLine(this.LastName + " is running...");
    }
    static void Main() {

        var p = new Person("Doe");
        p.Run(); 
    }
}


JavaScript
function Person(lastName) {

    this.LastName = lastName;

    this.run = function() {

        print(this.LastName + " is running...");
    }
}
var p = new Person("Doe", "Joe");
p.run(); 


Object With Properties And Methods (Function Constructor And Prototype)


  • Attaching the method run() to the prototype of the function constructor Person() is more efficient as the code of the method run() is not duplicated for each object.
  • You cannot use the Closure function.
  • Not as clear as the previous syntax (According to my taste).

C#
public class Person {

    public string LastName { get; set; }

    public Person(string lastName) {

        this.LastName = lastName;
    }
    public void Run() {

        Console.WriteLine(this.LastName + " is running...");
    }
    static void Main() {

        var p = new Person("Doe");
        p.Run(); 
    }
}



JavaScript
function Person(lastName) {

    this.LastName = lastName;
}
Person.prototype.run = function() {

    print(this.LastName + " is running...");
}
var p = new Person("Doe", "Joe");
p.run(); 


Reflection And Property


C#
    const BindingFlags GET_FLAGS = BindingFlags.Instance | BindingFlags.Public | 
                                   BindingFlags.GetField | BindingFlags.GetProperty;

 var p = new { LastName = "Doe" };

    Console.WriteLine(p.GetType().InvokeMember("LastName", GET_FLAGS, null, p, null));

    Console.WriteLine(p.LastName);


JavaScript
    var p = { LastName   : "Doe" };

    print(p["LastName"]);    

    print(p.LastName);



Reflection And Object


C#
public class Program {

    static void Main() {

        var p = new { LastName = "Doe", FirstName = "Joe" };

        foreach(var propertyInfo in p.GetType().GetProperties()) {

            Console.WriteLine(propertyInfo.Name + " = " + propertyInfo.GetValue(p, null).ToString());
        }
    }
}



JavaScript
var p = { LastName : "Doe", FirstName : "Joe" };

for(var propertyName in p) {

    print(propertyName + " = " + p[propertyName]);
}


Inheritance


C#
public class Person {

    public string   LastName  { get; set; }
    public string   FirstName { get; set; }
        
    public Person(string lastName, string firstName) {

        this.LastName  = lastName;
        this.FirstName = firstName;
    }
}
public class Employee : Person {

    public string Company  { get; set; }
    
    public Employee(string lastName, string firstName, string company) : base(lastName, firstName) { // <= Base constructor

        this.Company = company;
    }
    static void Main() {

        var e = new Employee("Doe", "Joe", "ACompany");     
    }
}



JavaScript
function Person(lastName, firstName) {

    this.LastName  = lastName;
    this.FirstName = firstName;
}
function Employee(lastName, firstName, company) {
     
    Person.call(this, lastName, firstName); // <= Base constructor
    this.Company = company;
}
Employee.prototype = new Person(); // Inheritance

var e = new Employee("Doe", "Joe", "ACompany");


Private Property


C#
public class Employee  {

    public string LastName             { get; set; }
    public string FirstName            { get; set; }
    private bool  _reservedParkingSpot { get; set; }

    public Employee(string lastName, string firstName, bool reservedParkingSpot) {

        this.LastName             = lastName;
        this.FirstName            = firstName;
        this._reservedParkingSpot = reservedParkingSpot;
    }
    public void Run() {
    
        Console.WriteLine(this.LastName + " reservedParkingSpot:" + _reservedParkingSpot);
    }
    static void Main() {

        var e = new Employee("Doe", "Joe", true);
        e.Run();
    }
}
 

JavaScript
function Employee(lastName, firstName, reservedParkingSpot) {
    var
        _reservedParkingSpot = reservedParkingSpot;

    this.LastName  = lastName;
    this.FirstName = firstName;

    this.run = function() {

        print(this.LastName + " reservedParkingSpot:" + _reservedParkingSpot);
    }
}
var e = new Employee("Doe", "Joe", true);
e.run();


Virtual Methods


  • In JavaScript all properties and methods are virtual and public

C#
public class Person{

    public string   LastName  { get; set; }
    public string   FirstName { get; set; }
        
    public Person(string lastName, string firstName){

        this.LastName  = lastName;
        this.FirstName = firstName;
    }
    public virtual void Run(){
    
        Console.WriteLine(this.LastName + " is running...");
    }
}
public class Employee : Person {

    public string Company  { get; set; }
    
    public Employee(string lastName, string firstName, string company) : base(lastName, firstName) { // <= Base constructor

        this.Company = company;
    }
    public override void Run() {

        Console.WriteLine(this.FirstName + " " + this.LastName + " is running...");
    }
    static void Main() {

        var e = new Employee("Doe", "Joe", "ACompany");
        e.Run();         
    }
}

JavaScript
function Person(lastName, firstName){

    this.LastName  = lastName;
    this.FirstName = firstName;

 this.run = function(){ 

        print(this.LastName + " is running...");
    }
}
function Employee(lastName, firstName, company) {
     
    Person.call(this, lastName, firstName); // <= Base constructor
    this.Company = company;

 this.run = function() { // <= Just override the method

        print(this.FirstName + " " + this.LastName + " is running...");
    }
}
Employee.prototype = new Person(); // Inheritance

var e = new Employee("Doe", "Joe", "ACompany");
e.run();


Optional Parameters


  • In C# optional parameters are available in version 4
  • In JavaScript all parameters are optional, with a default value of undefined

C#
public class Person { 

    public string LastName  { get; set; }
    public string FirstName { get; set; }
    public string Company   { get; set; }

    public Person(string lastName, string firstName, string company = null) {

        this.LastName  = lastName;
        this.FirstName = firstName;
        this.Company   = company;
    }
    static void Main() {

        var p = new Person("Doe", "Joe");
        Console.WriteLine("Company:" + p.Company);
    }
}

JavaScript
Person = function(lastName, firstName, company) {

    company = company || null; // Define a default value

    this.LastName  = lastName;
    this.FirstName = firstName;
    this.Company   = company; 
}
var p = new Person("Doe", "Joe");
print("Company:" + p.Company);


Extension Methods


  • Let's add a new format() method to a C# List and a JavaScript Array

C#
public static class Program { 

    public static string Format<T>(this List<T> l) {

        var b = new StringBuilder(1000);

        for(var i = 0; i < l.Count; i++) {

            b.Append(l[i]);
            if(i < l.Count-1)
                b.Append(", ");
        }
        return b.ToString();
    } 
    static void Main() {

        var l = new List<int>();
        l.Add(1);
        l.Add(2);
        l.Add(3);
        Console.WriteLine(l.Format());
    }
}


JavaScript
if (typeof Array.prototype.format !== 'function') {

    Array.prototype.format = function () {
        
        return this.join(", ");
    }
}

var a = [];
a.push(1);
a.push(2);
a.push(3);
print(a.format())



Static Member


C#
public class Person {

    public string LastName  { get; set; }
    public string FirstName { get; set; }

    public Person(string lastName, string firstName) {

        this.LastName  = lastName;
        this.FirstName = firstName;
    }
    public static Person Create(string lastName, string firstName) { // <= Static Member 

        return new Person(lastName, firstName);
    }
    static void Main() {

        var p = Person.Create("Doe", "Joe");
    }
}


JavaScript
function Person(lastName, firstName) {

    this.LastName  = lastName;
    this.FirstName = firstName;
}
Person.create = function(lastName, firstName) { // <= Static Member 

    return new Person(lastName, firstName);
}
var p = Person.create("Doe", "Joe");


Namespace


C#

namespace MyLibrary {

    public class Person {

        public string LastName  { get; set; }
        public string FirstName { get; set; }

        public Person(string lastName, string firstName) {

            this.LastName  = lastName;
            this.FirstName = firstName;
        }
    }
}
public class Program {

    static void Main() {

        var p = new MyLibrary.Person("Doe", "Joe");
    }
}


JavaScript
var MyLibrary = {

    Person : function (lastName, firstName) {

        this.LastName  = lastName;
        this.FirstName = firstName;
    }
}
var p = new MyLibrary.Person("Doe", "Joe");


Enum Type


C#
public enum EmployeeType {

    Developer,
    Manager  ,
}
public class Employee : Person {

    public string Company    { get; set; }
    public EmployeeType Type { get; set; }
    
    public Employee(string lastName, string firstName, string company, EmployeeType type) :base(lastName,firstName) {

        this.Company = company;
        this.Type    = type;
    }
    static void Main() {
        var e = new Employee("Doe", "Joe", "ACompany", EmployeeType.Developer);
        e.Run();         
    }
}
 

JavaScript
var EmployeeType = {

    Developer : 0,
    Manager   : 1
}
function Employee(lastName, firstName, company, type) {

    Person.call(this, lastName, firstName);
    this.Company = company;
    this.Type    = type;
}
Employee.prototype = new Person();

var e = new Employee("Doe", "Joe", "ACompany", EmployeeType.Developer);
e.run();


.NET Attribute


C#
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class SuperMethodAttribute : System.Attribute {

}        
public class TheClass {    

    [SuperMethod] // <= .NET Attribute
    public void Run() {

    }
}       
public class Program {    

    public static string GetSuperMethodName(object o) {

        foreach (var mi in o.GetType().GetMembers())
            foreach (object attribute in mi.GetCustomAttributes(true))
                if (attribute is SuperMethodAttribute)
                    return mi.Name;

        return null;
    }
    static void Main() {

        var theClass = new TheClass();
        Console.WriteLine("The SuperMethod is " + GetSuperMethodName(theClass));
    }
}


JavaScript
function TheClass() {

    this.run = function() {

    }
    this.run.SuperMethod = true; // <= JavaScript Attribute For A Function
}
function GetSuperMethodName(o) {

    for(var p in o)
        if(typeof o[p] === "function") 
            if(o[p].SuperMethod === true)   
                return p;

    return null;
}
var theClass = new TheClass();
print("The SuperMethod is " + GetSuperMethodName(theClass));


Dictionary<K,V> vs JavaScript Object


C#
var trace = new Dictionary<string, object>();

trace["Debug"]     = true;
trace["Trace"]     = "warning";
trace["TraceSize"] = 1000;

foreach(var e in trace) {

    Console.WriteLine(e.Key + " = " + e.Value.ToString());
}


JavaScript
var trace = { };

trace["Debug"]  = true;
trace["Trace"]  = "warning";
trace.TraceSize = 1000;

for(var key in trace) {

    print(key + " = " + trace[key]);
}



Dictionary<K,V> vs JavaScript Object - The ContainKey() vs in operator


C#
var trace = new Dictionary<string, object>() {

    { "Debug"    , true      },
    { "Trace"    , "warning" },
    { "TraceSize", 1000      }
};

if(trace.ContainsKey("Debug"))
    Console.WriteLine(trace["Debug"]);   


JavaScript
var trace = {
    Debug     : true     ,
    Trace     : "warning",
    TraceSize : 1000
};

if("Debug" in trace)                // Solution 1
    print(trace["Debug"]);

if(trace["Debug"] !== undefined)    // Solution 2
    print(trace["Debug"]);

if(trace.Debug !== undefined)       // Solution 3
    print(trace.Debug);



JavaScript Array


  • A JavaScript Array is not a C# array
  • JavaScript Array is neither an hybrid between array and list
  • A JavaScript Array is a Dictionary where the keys can only be integer
    • The property length always returns the max key

JavaScript Arrays can be used as

  • Array - Array<T>
  • List - List<T>
  • Stack - Stack<T>
  • Queue - Queue<T>

  • Array methods:

    • concat, indexOf, join, pop, push, reverse, shift, slice, sort, splice, unshift, valueOf.

With Extension Methods we can create the C# methods that we are used to.

C#
var a = new List<object>();

var b = new List<int>() { 1, 2, 3 };

var c = new List<string>() { "a", "b", "c" };


JavaScript
var a = [ ];

var b = [ 1, 2, 3 ];

var c = [ "a", "b", "c" ];



Iterating Through An Array - Recommended


  • The default way

C#
var a = new string[] { "a", "b", "c" };

for(var i = 0; i < a.Length; i++) {
 
    Console.WriteLine(a[i]);
}

JavaScript
var a = [ "a", "b", "c" ];
 
for(var i = 0; i < a.length; i++) {
 
    print(a[i]);
}


Iterating Through An Array - Not Recommended


C#
var a = new List<string>()  { "a", "b", "c" };

foreach(var i in a) {
 
    Console.WriteLine(i);
}


JavaScript
var a = [ "a", "b", "c" ];
 
for(var i in a) { // <= Iterate over the keys of the Object/Array, which happens to be indexes

    print(a[i]);
}


Iterating Through An Array - The Functional Way


  • The method forEach()
    • With JavaScript 5 (ecmascript 5), the Array type has a member function forEach()
    • With JavaScript 3, include the library: http://augmentjs.com

C#
var a = new List<string>()  { "a", "b", "c" };

a.ForEach(
     v => { Console.WriteLine(v); } // <= Lambda Statment
);


JavaScript
var a = [ "a", "b", "c" ];

a.forEach(
    function(v) { print(v); } // <= Lambda Statment
);


JavaScript Array Used As A Stack<T>


C#
var a = new Stack<string>();

a.Push("a");
a.Push("b");
a.Push("c");

while(a.Count > 0) {

     Console.WriteLine(a.Pop());
}


JavaScript
var a = [ ];

a.push("a");
a.push("b");
a.push("c");

while(a.length > 0) {

    print(a.pop());
}


JavaScript Array Used As A Queue<T>


C#
var queue = new Queue<int>();

queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
             
while(queue.Count > 0){
 
    Console.WriteLine(queue.Dequeue());
}


JavaScript
var queue = [];
 
queue.unshift(1);
queue.unshift(2);
queue.unshift(3);
 
while(queue.length > 0){
 
    print(queue.pop());
}



Lambda Expression


  • The following methods: filter(), forEach(), every(), map() are available for Array with ECMAScript 5 or include http://augmentjs.com

C#
var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

var evenNumbers = numbers.FindAll( i => i % 2 == 0 ); // <= Lambda Expression

evenNumbers.ForEach(n => {  // <= Lambda Statment

    Console.WriteLine(n); 
});


JavaScript
var numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ];

var evenNumbers = numbers.filter( function(i) { return i % 2 === 0; } ); // <= Lambda Expression

evenNumbers.forEach(function(n) {

    print(n);
});



LINQ


C#
public class Program {    

    static void Main() {

        var annoyingPeopleInHighSchool = new List<Person>() {

            new Person("Descartes", "Rene"        ),
            new Person("Pascal"   , "Baise"       ),
            new Person("Laplace"  , "Pierre-Simon")
        };

        var funnyPeopleInHighSchool = from p in annoyingPeopleInHighSchool
            where p.LastName == "Laplace"
            select p;
            
        foreach(var p in funnyPeopleInHighSchool) {

            Console.WriteLine(p.LastName);
        }
    }
}




JavaScript
var annoyingPeopleInHighSchool = [

    new Person("Descartes", "Rene"        ),
    new Person("Pascal"   , "Baise"       ),
    new Person("Laplace"  , "Pierre-Simon")
];

var funnyPeopleInHighSchool = annoyingPeopleInHighSchool.filter(function(p) {

    return p.LastName === "Laplace" ? p : undefined;
});

for(var p in funnyPeopleInHighSchool) { 

    print(funnyPeopleInHighSchool[p].LastName);
}



GetType() vs getType()


C#
int i = 1;
Console.WriteLine(i.GetType().Name);

bool b = true;
Console.WriteLine(b.GetType().Name);

String s = "Hi";
Console.WriteLine(s.GetType().Name);

DateTime d = DateTime.Now;
Console.WriteLine(d.GetType().Name);

int [] ia = new int[3];
Console.WriteLine(ia.GetType().Name);




JavaScript
var i = 1;
print(getType(i));

var b = true;
print(getType(b));

var s = "Hi";
print(getType(s));

var d = new Date();
print(getType(d));

var ia = [];
print(getType(ia));

function getType(v) {

    var type;
    if (v === null)
        return "null";
    if (typeof v === 'undefined')
        return "undefined";

    type = Object.prototype.toString.call(v);
    type = type.replace("[object ", "").replace("]", "");
    return type;
}




Inheriting from a List<T> vs Inheriting From An Array


C#
public class PersonList : List<Person> {

    public string Name;

    public PersonList(string name) {

        this.Name = name;
    }
    public int GetSumYears() {

        var total = 0;
        foreach (var p in this)
            total += p.BirthDate.Year;
        return total;
    }
}
public class Program {    

    static void Main() {

        var personList = new PersonList("MyList");

        personList.Add(new Person("Descartes", "Rene"        , new DateTime(1596, 3, 31)));
        personList.Add(new Person("Pascal"   , "Baise"       , new DateTime(1623, 6, 19)));
        personList.Add(new Person("Laplace"  , "Pierre-Simon", new DateTime(1749, 3, 23)));

        Console.WriteLine(String.Format("Total {0} {1}", personList.Name, personList.GetSumYears()));
    }
}


JavaScript
function PersonList(name) {

    this.Name = name;

    this.GetSumYears = function() {
        var
            i     = 0,
            total = 0;

        for(i = 0; i < this.length; i++)
            total += this[i].BirthDate.getFullYear();

        return total;
    }
}
PersonList.prototype = []; // <= Inheritance from an Array

var personList = new PersonList("MyList");

personList.push(new Person("Descartes", "Rene"        , new Date(1596, 3-1, 31)));
personList.push(new Person("Pascal"   , "Baise"       , new Date(1623, 6-1, 19)));
personList.push(new Person("Laplace"  , "Pierre-Simon", new Date(1749, 3-1, 23)));

print("Total "+personList.Name+" "+personList.GetSumYears());

No comments:

Post a Comment