Apr 14

     The first part of this topic has explained what prototypes are and how they are used. Recall that, JS chooses rather to link the prototype to the blank object than to duplicate it. This results in the share of property code and method code - the more they share, the less memory they require. Carefully read that they share the code, not the memory space. Looking at the following example:

function X() {
}
X.prototype = {
     x: 0,
     getX: function(){
          return this.x;
     },
     setX: function(new_x){
          this.x = new_x;
     }
}
myNum = new X();
yourNum = new X();
myNum.setX(8);
document.write(yourNum.getX());   // print "0"

     After the 2 objects are created,  they contain nothing. The call setX() on “myNum”, which is available upon its prototype chain, sets “this.x” to the specified number. The “this” keyword in this context references to the object “myNum”, not the prototype. It does not change the “x” in the prototype. You might check it out by yourself. The next line calling getX(), is also found in its prototype chain. The reference to “this.x” does not directly mean the “x” in the prototype, but it is indirectly referenced because the property “x” is not in the object itself. That is, “this.x” is later found in its prototype chain.
     The art of JS language design, as you see, is extremely fascinating. The memory used is minimized as less as possible. However, the following code can cause a logical error that is unknown to most programers.

function X(){
}
X.prototype = new function(){
     var x;
     this.getX =  function(){
          return x;
     }
     this.setX = function(new_x){
          x = new_x;
     }
}
myNum = new X();
yourNum = new X();
myNum.setX(8);
document.write(yourNum.getX());   // print "8"

     Differently coded, the sematic is almost the same except that “x” is set local or private. You might think that the above is better. However, unlike local variables in the constructor that are saved as separate closures for separate objects, “x” is shared among objects that link it as their prototype. The reason is that, the prototype is an object that has been instantiated long before. The save of the closure was done only once by the time the prototype was instantiated. As a result, there is only one closure shared among objects. So, be very careful if you wish to use private variables, which is not supported directly by JS.
     Prototypes are not only used for object instantiation, but also for primitive types. Surprising? Remember that, reference types and corresponding primitive types are differentiated only by the presence of the “new” keyword. But, they do share the same constructor. The “new” keyword simply gives you a blank object linked to its prototype. Without “new” keyword, a memory is also allocated to that primitive value and linked to the prototype as well. The “this” keyword refer to the primitive data instead of object. That is a reason why we have a wonderful code work nicely.

Number.prototype.isOdd = function(){
     return (this%2)? true : false;
}
var a = 7;
if(a.isOdd())
     document.write("Is it really odd?");

JS Prototypes

     By now, I assume that you are familiar with prototypes. The following referencing is meant to check your understanding. It can confuse you more if you do not really understand. Think of what they are before execute it. The weird syntax is used by mean to guide you to the answer. There is a saying that thousands words cannot better explain than a picture. Looking up this picture will also guide you to the answer. I got it from MollyPages.org

var Foo = Function("", "this.x = 6;");
var myObj = new Foo();
var myList = [
     myObj.__proto__,
     myObj.__proto__.constructor,
     Foo.prototype,
     Foo.__proto__,
     Foo.__proto__.constructor,
     Object.prototype.__proto__,
     myObj.__proto__.constructor.__proto__.constructor,
]
for(index in myList){
     document.write("<li>" + myList[index] + "</li>");
}

Onion_sure

กุบ้าได้ที่แล้ว หึหึ . . .
so d0m3z

Apr 14

     Prototypes are class-like objects that act as templates for prototype-based languages. In this topic we will get through it in detail. Recall that functions are primitive data. Looking at them this way, rather than procedural way, will help you better understand the content.
     Since functions are like other variables, these following code should not be surprising - they can posses some properties and methods like primitive strings.

var myObj = new function(){
     this.x = 6;
}
var foo = function() {
     return this.x;
}
document.write(foo.call(myObj));   // print "6"
document.write(foo.apply(myObj));   // print "6"
document.write(typeof foo.prototype);   // print "object"

     The “prototype” property of the function foo, as you can see, is an object of reference type. It points to an ordinary object. It is, in deed, a prototype linked when instantiating a new object. Let’s inspect in detail before going further.

var suspectingObject = foo.prototype;
document.write(suspectingObject.constructor);
suspectingObject.sayHi = function() {
     alert("Hi!");
}

     This object (the prototype) has a reference back to the function it belongs to. The print out, therefore, shows the function “foo”. That is, functions and their prototypes are doubly linked back and forth using “.prototype” and “.constructor”. The last statement simply shows the dynamic declaration possible as other ordinary objects.
     You can even change the entire thing by:

foo.prototype = new function(){
     this.bar = "bar";
     this.show = function(){
          alert(this.bar);
     }
     this.constructor = foo;
}

     Changing the reference to prototype to a newly created object (with any style of declaration) is also possible, but make sure that the reference back to the constructor is set correctly. Be very careful because you are working manually.
     It is now high time to know the automatic machanism of the object instantiation. Suppose that a new object is instantiated with a function named “Foo” acting as the constructor. As far as you know, the “new” keyword simply gives you a blank object, and calls Foo() in the context of that object’s scope. Moreover, the “new” object is linked to the “Foo.prototype” object. Remark that, the prototype now is pointed to by many objects.
     The following code will help you closer inspect the prototypes. Unfortuantely, it works only on Firefox and Netscape.

function Car(){
     this.speed = 10;
}
Car.prototype.color = "black";
var myCar = new Car();
for(key in myCar.__proto__)
     document.write(key + ": " + myCar.__proto__[key]);
document.write(myCar.__proto__.constructor);

     The special property “__proto__” is provided for every object, referencing to the prototype of the function used as its constructor. Traversal through myCar.__proto__ simply prints out the prototype’s properties (eg. color). The last statement, of course, prints out the function “Car”.
     At this moment, you can go back the case when the called properties or methods are not available in the specified object. The prototype chain means the linkage connected fomr an object to another by “__proto__”. JS will climb up the chain searching for those unavailable properties and methods . The word “chain” suggests that the prototype object can be instatntiated from another function, and form a long chain.

Onion_nga

 นี่แค่เริ่มต้นคร้าบพี่น้อง
 so d0m3z

Apr 14

     All along the way we have discussed, scoping was gradually guided and mentioned. Scoping in JS, as an OOP language that supports nested scoping, consists of serveral finer points than others, which do not. Referencing to a variable has to take in consideration the object’s scope and function’s scope. That’s why it becomes confusing stuff. Additionally, variables’ life time also concern for some extent. We begin with function’s scope first.
     Normally, declaring a variable, the variable name is preceded by the “var” keyword to make it locally scoped in that context. Like other languages, local variables (the word “variable” also includes functions) are deallocated when function execution is done. Occasionally, those variables are necessary to exist for future use. Programmers might be familiar with the code below.

function getAdder(increment){
     return function(num){
          return num + increment;
     }
}
var addFive = getAdder(5);
document.write(addFive(6));

     JS responsibly takes care of the nested function. In the case where there is a reference back to any of the local variables, the environment will not be garbage collected. Say technically that, deep binding is implemented and its closure is saved somewhere.
     Generally, such a case is not going to happen. However, you frequently but unknowingly code scripts that require deep binding as such the case. Consider the reason why the following code works perfectly.

function X(){
     var x;
     this.setX = function(new_x){
          x = new_x;
     }
     this.getX = function(){
          return x;
     }
}
var myNum = new X();
myNum.setX(6);
document.write(myNum.getX());   // print "6"

     The local variable “x” in the constructor still exists because of the reference held by “myNum”. This enables a really useful characteristic, that is variable protection. Local variables, saved as a closure when the constructor is done, are invisible to others not in the context. It is a technique used generally for private properties and methods. Remark for the code above that calling “this.x” and “x” have different meanings. Calling “x” will reference to the variable named “x” within the scope first, and look outer statictially if not available. Whereas, calling “this.x” would reference to the property named “x” within the concerned object context, and look up its prototype chain if not avaiable. Prototype chain will be discussed in the next topic.
     What if a variable is used without declaration? Either good or bad, it will be immediately allocated at the runtime after JS has found in none of the scopes. Then, at which scope is it going to be? The answer is simply at where JS realizes the absence of the variable - the outer most one. Now, you know where and when the “var” keyword is trivial. Grobal variables can be declared anywhere just without “var” keyword, if and only if, the variable name is never used before.
     Now, let’s turn our attention to another consideration, object’s scope. Variables are involved object’s scope when they are called with dot notation (eg. myNum.getX(), this.x ). As I have already mentioned at least twice that, we all are working inside “window” object as if “with(window)” were wrapping us. Condider the following code.

function foo(){
     this.text = "Hello";
     this.getText = function(){
          return this.text;
     }
     return this.text;
     this.bar = "bar";   // ignored code
}
myObj1 = new foo();
myObj2 = foo();

     Calling a function with the “new” keyword changes the object’s scope to the newly created one. As a result, the “this” keywords in foo() reference to “myObj1″. The “return” statement only ends the constructor execution, having no mean to return “this.text”. Calling without the “new” keyword, as “myObj2″, the object’s scope would not change. Still, the “this” keywords reference to “window” object as if they were outside foo(). Being executed as an ordinary function, the “return” simply sends back the”this.text”, which in fact is, “window.text”.
     Changing the object’s scope is not often the case. Sometime, it is needed to call a function in the context of another object - which is not the current one. Remember that, the reference to a variable is considered as in another object’s scope, if the object is explicitly specified using dot notation. We temporarily ignore the case we have with(…) structure. The following code suggests a tricky way to do so.

myObj = new Object();
function bar(arg1, arg2){
     return arg1 + arg2;
}
myObj.bar = bar;
myObj.bar("Hello", "World");
bar.call(myObj, "Hello", "World");
bar.apply(myObj, ["Hello", "World"]);

     “myObj” was created long before. The easiest understandable way is adding the function “bar” as a method of “myObj”, then calling it. The other approaches are to use either .call() or .apply(). Despite “bar” being a function, it can posses some properties and methods, just like primitive strings. The arguments for .call() are, repectively, the object we wish to execute under its scope and function arguments. Similary, the method .apply() takes almost the same things except that the function arguments are required to be of type array. This array will be passed in as the special array “arguments” in the function if you can remember.
     Another careful point that is most confusing is when the structure with(…) is used. Calling a variable might reference to the function’s scope or object’s scope. Normally, the higher priority is given to object’s scope. In other words, this is the only place where the properties and methods of an object shadow the local variables. Always be careful when referening a variable even if you yourself do not use with(…), or you already forgot that we were inside with(window).
     For those who study this tutorial just for client-sided web programming, like working with DOM, Ajax or whatever, coming up to this topic should be much enough. The rest of this tutorial would rather be of higher level. We will talk about in detail the prototype and techniques to implement inheritance. Let’s go together if you really want to.

Onion_complain

 โอ้ว . . . ยังไม่จบอีกเหรอเมิง
 so d0m3z

« Previous Entries