We can use a tool in Visual Studio when debugging to check whether two objects point to the same instance. First, add the objects/variables that we want to check to Watch list. Right click one of the variables, then select Make Object ID.
After doing this, an ID will be displayed on the Value column in this format '{ID_Number#}'. At the same time, all other objects that point to the same instance will have this displayed on their values as well.
If two or more variables have the same ID number then it means that they point to the same instance.
If we rather would like to check the objects manually, we could use Object.ReferenceEquals(object1, object2) method that will return a boolean value.
Friday, 23 January 2015
Tuesday, 13 January 2015
Using JavaScript Prototype for Object Oriented Approach
Prototype property
Every object in JavaScript has a prototype. This prototype can be seen by accessing __proto__ property in recent modern browsers except IE.
var n = 5; console.log(n.__proto__); var myObj = {}; console.log(myObj.__proto__);
Function prototype property
There is another similar term that is quite confusing in JavaScript world, it is the prototype property. This is not the real prototype property like the one above. However this is a property that is found in every function in JavaScript. I prefer to call this property; function prototype.
function Person(firstname, lastname) { this.firstname = firstname; this.lastname = lastname; this.fullName = function () { return this.firstName + ' ' + this.lastName; } } console.log(Person.prototype); // below will yield 'undefined' because it is not a function var n = 5; console.log(n.prototype); // this will be false as a function prototype is not the same as its prototype property Person.prototype == Person.__proto__;
Creating object with new keyword
When we initialise a new object with new keyword, the object's real prototype will point to the constructor function's function prototype property.
var john = new Person('john', 'king'); // john's prototype will point to Person's function prototype property console.log(john.__proto__ == Person.prototype) // trueThe new object will have whatever defined inside the constructor function plus access to whatever in its prototype. So if we add more properties to the constructor function's function prototype, these will be accessible by the created objects. This will be explained more in details below.
A very important rule that need to be remembered from here is:
newObject.__proto__ = TheFunction.prototype
Prototypes chain
In JavaScript, when an object property is called, if it is not found within the object, JavaScript will try to traverse up it's prototypes chain to find it. If it already reaches the root but still cannot find the property, undefined will be returned.
var animal = { name: 'animal', eats: true }; var fish = { name: 'fish', swims: true }; // set fish prototype to animal fish.__proto__ = animal; var tuna = { name: 'tuna', canBeCanned: true }; // set tuna prototype to fish tuna.__proto__ = fish; console.log(tuna.swims); console.log(tuna.eats);Below is the structure created (on Firebug):
As we can see tuna's prototype is fish object and fish's prototype is animal object. The text in bold are properties that are available to the containing objects.
Adding a property to a prototype chain
When we have an established prototypes chain then if we added a new property to one of the prototype objects in the chain, this new property would be accessible by the lower objects in the chain.
// based on the example above we add a new property to animal animal.moves = true; console.log(tuna.moves) // lower objects in the chain can access it // we can also add a new property through a prototype link // this example below add a new property at animal's level because we have set fish.__proto__ = animal fish.__proto__.breathes = true; console.log(tuna.breathes)
Using these prototype behaviours for object oriented approach
Having knowledge of prototype behaviours described above, we can implement object oriented concept in our JavaScript codes. We will also need to use function prototype and new keyword to set up relationships as the __proto__ property is not available in some browsers. As an example, we could have something like this:
function Coder() { this.name = 'coder'; this.code = function () { return "coding now"; } } function JSCoder() { this.name = 'JSCoder'; this.writeSomeJSCodes = function () { return "writing: this.__proto__ = . . ."; } } // set up the relationship JSCoder.prototype = new Coder(); // this is saying that every newly created JSCoder object will have its prototype property points to a Coder object var jack = new JSCoder(); // because we have set above JSCoder.prototype = new Coder() // and because of the rule: newObject.__proto__ = TheFunction.prototype // then this one below is implemented implicitly when jack is created: // jack.__proto__ = JSCoder.prototype which equals to a Coder object ( new Coder() ) console.log(jack.writeSomeJSCodes()); console.log(jack.code()); // we can also add a new property to a function prototype then it will be accessible by existing child object(s) JSCoder.prototype.debugging = function () { return 'debugging some codes' }; // this is saying that because of the rule: newObject.__proto__ = TheFunction.prototype // when a new JSCoder object is created: var jack = new JSCoder() // then this will apply: jack.__proto__ = JSCoder.prototype // and JSCoder.prototype has been set to a Coder object ( new Coder() ) // so when a new property is added, // JSCoder.prototype is a Coder object plus the new property // thus jack's prototype ( jack.__proto__ ) is a Coder object plus the new property console.log(jack.debugging());
What will happen if we modify the function prototype to point to a new object? Existing objects will not be affected, however new objects created after the modification will have their prototypes point to the new object.
// modify JSCoder function prototype to point to a new object JSCoder.prototype = { sing: function () { return 'singing' } }; console.log(jack); // existing objects' prototypes do not change // however new objects' prototypes will point to the new object var jim = new JSCoder(); console.log(jim);
References and further readings:
A Plain English Guide to JavaScript Prototypes
Understanding “Prototypes” in JavaScript
Understanding JavaScript Prototypes
Prototypal inheritance
OOP in JS, Part 2 : Inheritance
Labels:
JavaScript
Monday, 5 January 2015
Implementing Asynchronous Tasks with $q in AngularJS
AngularJS has provided $q service that can be used to implement asynchronous tasks. It uses deferred objects and the promises they return to accomplish asynchronous runs.
A basic example of using $q:
We can also return an object when the task is completed. To do this, just pass the object as an argument to the resolve() function instead of nothing. Below is an example:
When resolving a deferred object, we can use deep nesting functions if required. As long as the deferred object variable is accessible, this should not be an issue:
A basic example of using $q:
function myAsyncFunc() { // create a deferred object var deferredObject = $q.defer(); . . . // if for a reason, we want to cancel this task if (errorOccured) { deferredObject.reject('an error has occured'); return deferredObject.promise; } // after the job is completed, call resolve() deferredObject.resolve(); . . . // return the promise return deferredObject.promise; } // then on the caller myAsyncFunc().then( // success (when resolve() was called) function() { alert('success') }, // error (when reject() was called) function(reason) { alert('failed: ' + reason) } )
We can also return an object when the task is completed. To do this, just pass the object as an argument to the resolve() function instead of nothing. Below is an example:
function myAsyncFunc() { var myObject = . . . deferredObject.resolve(myObject); } // then on the caller, we can use the passed object myAsyncFunc().then( // success function(passedObj) { . . . } );
When resolving a deferred object, we can use deep nesting functions if required. As long as the deferred object variable is accessible, this should not be an issue:
var deferredObject; // need to make sure that this deferred object variable will be accessible from inside nesting function function myAsyncFunc() { // create a deferred object deferredObject = $q.defer(); . . . nestedOne(); // return the promise return deferredObject.promise; } function nestedOne() { nestedTwo(); } function nestedTwo() { deferredObject.resolve(); }
Labels:
AngularJS
Subscribe to:
Posts (Atom)