Showing posts with label Demo. Show all posts
Showing posts with label Demo. Show all posts

Monday, February 24, 2014

JavaScript Best Practices: Why to avoid global variables and objects in JavaScript?

Learning AngularJS; Guide for beginners:

In this article I would try to explain the issue can be occurred due to global variable declaration if it is not declared global intentionally.

As we discussed in previous article JavaScript Best Practices : Strict mode In JavaScript if you are not using strict mode of ECMAScript 5 then assigning value to a variable which is not declared yet, then a global variable of that name will automatically be created.



See demo here.



(function() {
  myVar = 'Hello, Undeclared Variable!';
  alert(foo)  //=>; Hello, Undeclared Variable
})();

alert(myVar)  //=>; Hello, Undeclared Variable

So it is important to always declare your variables before initialization.

See demo here.

(function() {
  var myVar = 'Hello, Undeclared Variable!';
  alert(foo)  //=> Hello, Undeclared Variable
})();

//on accessing out side of scope ReferenceError: myVar is not defined
try {
  alert(myVar)
} 
catch (e) {
  alert("Error :" + e);
}

How it can cause error?


When global variables sneak into your code they can induce troubles. Particularly in applications with concurrency.

In the following example two different function using counter in loop without declaration which causes both to point same global variable.

see here without concurrency

var countOnetoTen = function() {
console.log("countOnetoTen started");
for (counter = 1; counter <= 10; counter += 1) {
         console.log(counter);
     }
 };
  countOnetoTen();  //=> 1 2 3 4 5 6 7 8 9 10

var countEleventtoTwenty = function() {
console.log("countEleventtoTwenty started");
for (counter = 1; counter <= 10; counter += 1) {
         console.log(counter+10);
     }
 };
  countEleventtoTwenty(); //=> 11 12 13 14 15 16 17 18 19 20// 
Both loops increment counter at the same time, which causes strange behavior in concurrency. With small amount of loops counter it is not observable, but it can be problematic in any case. As if two function working concurrently and accessing the same global variable. There can be a situation
  1. countOnetoTen() started set counter = 1
  2. countOnetoTen() : printed counter and increment counter++ //counter = 2
  3. countOnetoTen() : printed counter and increment counter++ //counter = 3
  4.  countEleventtoTwenty() started and set counter = 1
At this point counter is set to 1 while countOnetoTen() already have printed 1 2 and in next iteration it will find counter set to 1 and will print 1 again.
window.setTimeout(countEleventtoTwenty , 10);
window.setTimeout(countOnetoTen, 10);  //=> 2 3 7 8 9
  
this Keyword as global object

Sometime you can use 'this' in method definitions to refer to properties of the method's object.
var obj = {
prop: 'foo',
myFun: function() {
alert(this.prop);
}
};

obj.myFun();  //=> print foo
But 'this' does not conform the normal rules of scope in JavaScript. One might expect 'this' to be available with the same value via closure in the callback specified inside the method here. see here demo
var obj = {
  prop: 'foo',
  myFun: function() {
    window.setTimeout(function() {
      alert(this.prop);
    }, 3000);
  }
};

obj.myFun(); //=> alert undefined
Here in callback 'this' got bound to the global object which do not contains the definition of prop. To get around this, assign the object reference to a regular variable that will have the same value inside the callback definition. see here demo
var obj = {
prop: 'foo',
myFun: function() {
  var that = this;
  window.setTimeout(function() {
    alert(that.prop);
  }, 3000);
 }
};

obj.myFun();  //=> alert foo
The keyword 'this' is actually dynamically assigned whenever a function is invoked. When a function is invoked as a method, i.e. obj.method(), 'this' is bound to 'obj'. But when a function is invoked by itself 'this' is bound to the global object.
var text = 'Hello, world!';
var printText() {
alert(this.text);
}

printText();  //=> Hello, world!
This is true even of functions that were defined as a method.
var obj = {
  prop: 'foo',
  myFun: function() {
   alert(this.prop);
  }
};
When the subroutine is invoked without reference of object ie obj with it, 'this' becomes the global namespace.
var myFun = obj.myFun;
myFun();  //=> undefined
Method invocation and function invocation are two of the invocation patterns in JavaScript. A third is apply invocation, which gives us control over what 'this' will be assigned to during function execution.
myFun.apply(obj, null);  //=> foo
'apply' is a method on Function. The first argument is the value that 'this' will be bound to. Successive arguments to apply are passed as arguments to the function that is being invoked. The last invocation pattern in JavaScript is a constructor invocation. This Pattern was projected to offer a means to make new objects that would seem familiar to programmers who are used to programming with classes.
var Duck = function(name) {
this.name = name;
};
Duck.prototype = {
query: function() {
  alert(this.name + ' says, "quack"');
}
};
When a instance is created with new keyword in front of it, a new object is initiated and is linked to 'this' keyword when function executed.
var donald= new Duck('Donald');
  donald.query();  //=> donald says "quack"
When a new object is created with 'new', the prototype of the new object is set to the prototype of the constructor function. So the new object inherits all of the attributes of the constructor's prototype value. In this case, new duck objects inherit the 'query' method from Duck.prototype.
var daffy = new Duck('Daffy');
daffy.query();  //=> Daffy says "quack"
If a constructor function is called without the 'new' keyword, it is invoked with the ordinary function invocation pattern. So 'this' is assigned to the global object instead of to a newly created object. That means that any attributes assigned to the new object by the constructor function become global variables!
var gotcha = Duck('gotcha!');
gotcha.query();  //=> TypeError: gotcha has no properties
Constructor invocation is pretty complicated and prone to disastrous global variable creation. Here is a neater path to produce new objects that inherit from other targets This defines Object.create, a method that simplifies the behavior of the 'new' keyword. This method was invented by Douglas Crockford.
if (typeof Object.create !== 'function') {
Object.create = function(o) {
var F = function() {};
F.prototype = o;
return new F();
};
}
Object.create(obj) returns a new object that inherits all of the attributes of obj. The 'duck' prototype object here defines a 'clone' method that wraps around Object.create to customize new 'duck' objects as they are created.
var duck = {
query: function() {
print(this.name + ' says "quack"');
},
clone: function(name) {
var newDuck = Object.create(this);
newDuck.name = name;
return newDuck;
}
};

var buffy = duck.clone('buffy');
buffy.query();  //=> buffy says "quack"
In addition to inheriting 'query', new ducks also inherit 'clone'.
var buffy2 = buffy.clone('buffy2');
buffy2.query();  //=> buffy2 says "quack"
Methods and attributes are inherited, not copied. If you change the definition of 'clone' on 'duck' at this point, the change will be reflected in duck objects that have already been created.
buffy2.hasOwnProperty('clone')  //=> false
buffy.hasOwnProperty('clone')  //=> false
duck.hasOwnProperty('clone')  //=> true

Tuesday, November 5, 2013

Kendo-UI Data-Source CRUD (Create,Retrieve,Update and Delete) Operations

You may also like to see:
  1. JavaScript : Prototype Property and Inheritance  
  2. JavaScript : Closures Concept with examples

Here I am going to create a little application for maintaining to-dos. This demo application allows the user to:
  1. Add new To-do 
  2. Done the To-do by clicking CheckBox 
  3. Remove all Done To-dos 
  4. Filter the To-dos for complete, Incomplete or All 
Create a template to render the datasource, It will contain three columns
  1. CheckBox to show To-do status 
  2.  To-do Id column 
  3. To-do description

Here is the code:
Add HTML for taking user input to insert into datasource:
Add A Todo Enter a to do item description
Add a button so we can delete item from datasource (It will be used within a table given below):

Create a table in which we going to render the templates datasource also contain a button to filter data(show complete,Incomplete or All To-dos), Delete button in it rows:
Done ID Task
Show:
Actions:
Get the Datasource template we define in first part:
// To Do Item Template
  // -------------------

  var template = kendo.template($("#template").html());
Add predefined data into datasource so it renders initially:
var tasks = [
    { id: 1, done: false, description: "do stuff"},
    { id: 2, done: false, description: "more stuff"},
    { id: 3, done: true, description: "this stuff to do"},
    { id: 4, done: false, description: "that stuff we need"}
  ];
Now create a datasource:
// Build the data source for the items
  var dataSource = new kendo.data.DataSource({ data: tasks });
Bind the change event to datasource so whenever a new item added to datasource its HTML automatically get refreshed:
// When the data source changes, render the items
  dataSource.bind("change", function(e) { 
    var html = kendo.render(template, this.view());
    $("#todos tbody").html(html);
  });
Load the items from task array to datasource using:
// Initial read of the items in to the data source
  dataSource.read();
Bind the add button so new item gets added to datasource and HTML get refreshed:
// Handle adding a new to do item
  $("#add").click(function(e){
    e.preventDefault();

    var $todo = $("input[name='description']");

    currentId += 1;
    dataSource.add({
      id: currentId,
      done: false,
      description: $todo.val()
    });

    $todo.val("");
    $todo.focus();
  });
Handle the remove button event:
// Handle removing cleared items
  $("#remove-done").click(function(e){
    e.preventDefault();

    var raw = dataSource.data();
    var length = raw.length;

    // iterate and remove "done" items
    var item, i;
    for(i=length-1; i>=0; i--){

      item = raw[i];
      if (item.done){
        dataSource.remove(item);
      }

    }
  });
Removing multiple items from datasource on checking the checkboxes and clicking Remove Done Items
// Handling clicking the "done" checkboxes
  $("#todos").on("change", ".done", function(e){
    var $target = $(e.currentTarget);
    var id = $target.data("id");
    var item = dataSource.get(id);
    item.set("done", $target.prop("checked"));
  });
We can also filter by hiding and showing some values, as we added three option in above table for filtration, so now on the basis of user selection of filter we will pass a value for done column of datasource it will filter the data source accordingly:
// Handle the filters for showing the desired items
  $("#filter").change(function(e){
    //get the dropdown selected value
    var filterValue = $(e.currentTarget).val();
    
    //set the filter for done column with operator equals to
    var filter = {
      field: "done",
      operator: "eq"
    };

    //set the filter value as per user selected dropdown value
    if (filterValue === "done"){
      filter.value = true;
    } else if (filterValue === "not done"){
      filter.value = false;
    } else {
      filter = {};
    }

    //now filter the datasource by passing this filter
    dataSource.filter(filter);
  });
Here is the working JsFiddle demo for reference or you can see Stackoverflow

You may also like to see:
  1. JavaScript : Prototype Property and Inheritance  
  2. JavaScript : Closures Concept with examples
Life insurance policy, bank loans, software, microsoft, facebook,mortgage,policy,