Showing posts with label Object. Show all posts
Showing posts with label Object. Show all posts

Friday, October 03, 2008

JavaScript函数调用时的作用域链和调用对象是如何形成的及与闭包的关系

1、javascript解析器启动时就会初始化建立一个全局对象global object,这个全局对象就拥有了一些预定义的全局变量和全局方法,如Infinity, parseInt, Math,所有程序中定义的全局变量都是这个全局对象的属性。在客户端javascript中,Window就是这个javascript的全局对象
2、当javascript调用一个function时,会生成一个对象,称之为call object(调用对象),function中的局部变量和function的参数都成为这个call object的属性,以免覆写同名的全局变量。
调用对象: ECMAScript规范术语称之为activation object(活动对象)。
3、javascript解析器每次执行function时,都会为此function创建一个execution context执行环境,在此function执行环境中最重要的一点就是function的作用域链scope chain,这是一个对象链,由全局对象调用对象构成,对象链具体构成过程见下面说明。
4、当javascript查询变量x的值时,就会检查此作用域链中第一个对象,可能是调用对象或者是全局对象,如果对象中有定义此x属性,则返回值,不然检查作用域链中的下一个对象是否定义x属性,在作用域链中没有找到,最后返回undefined。
5、当javascript调用一个function时,它会先将此function定义时的作用域作为其作用域链,然后创建一个调用对象,置于作用域链的顶部,function的参数及内部var声明的所有局部变量都会成为此调用对象的属性。
6、this关键词指向方法的调用者,而不是以调用对象的属性存在,同一个方法中的this在不同的function调用中,可能指向不同的对象。
7、The Call Object as a Namespace
(function() {
// 在方法体内用var声明的所有局部变量,都是以方法调用时创建的调用对象的属性形式存在。
// 这样就避免与全局变量发生命名冲突。
})();
8、javascript中所有的function都是一个闭包,但只有当一个嵌套函数被导出到它所定义的作用域外时,这种闭包才强大。如果理解了闭包,就会理解function调用时的作用域链和调用对象,才能真正掌握javascript。
9、当一个嵌套函数的引用被保存到一个全局变量或者另外一个对象的属性时,在这种情况下,此嵌套函数有一个外部引用,并且在其外围调用函数的调用对象中有一个属性指向此嵌套函数。因为有其他对象引用此嵌套函数,所以在外围函数被调用一次后,其创建的调用对象会继续存在,并不会被垃圾回收器回收,其函数参数和局部变量都会在这个调用对象中得以维持,javascript代码任何形式都不能直接访问此对象,但是此调用对象是嵌套函数被调用时创建的作用域链中的一部分,可以被嵌套函数访问并修改。

Wednesday, October 01, 2008

jQuery Object Accessors example


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="text/javascript" charset="utf-8" src="/lib/jquery/jquery-1.2.6.js"></script>
<style type="text/css" media="screen">
p {
margin: 3px;
}
.first {
color: #f90;
}
.second {
color: #f00;
min-height: 20px;
border: #949 1px solid;
margin: 5px 0px;
}
.three {
font-size: 18px;
color: blue;
border: blue 1px solid;
cursor: pointer;
}
</style>
</head>
<body>
<div id="d1">div#d1</div>
<div class="first">div.first</div>
<div class="first">div.first</div>
<div class="first">div.first</div>
<p>one</p> <div><p>two</p></div> <p>three</p>
Reversed - <div id="reversed"></div>
To do list: <span class="three">click here to change</span>
<span></span>
<ul>
<li>Eat</li>
<li>Sleep</li>
<li>Play</li>
<li>Be merry</li>
</ul>
<button>Change colors</button>
<span>this span innerText will be changed.</span>
<div class="second"></div>
<div class="second"></div>
<div class="second"></div>
<div class="second"></div>
<div class="second"></div>
<div class="second" id="stop">colors change will stop here</div>
<div class="second"></div>
<div class="second"></div>
<div class="second"></div>
<div class="second"></div>

<input type="checkbox" name="t1" value="test1" id="t1"/>checkbox#t1

<script type="text/javascript" charset="utf-8">
$("span.three").click(function () {
// console.log(arguments);
$("li").each(function(){
$(this).toggleClass("first");
});
});
$("button").click(function () {
$("div.second").each(function (index, domEle) {
// this == domEle, $(this) == jQuery Object
$(domEle).css("backgroundColor", "yellow");
if ($(this).is("#stop")) {
$("span").not(".three").text("Stopped at div index #" + index);
return false; // break loop
}
});
});
$("#reversed").html($("p").get().reverse().map(function(elem){
return elem.innerHTML;
}).join(','));
$("p").eq(2).text("four");
$("span, ul, li", document.body).click(function (e) {
e.stopPropagation();
var domEl = $(this).get(0);
$("span:first").text("Clicked on - " + domEl.tagName);
});
$("div").click(function () {
// this is the dom element clicked
var index = $("div").index(this);
$("span:last").text("That was div index #" + index);
});
$(document.body).click(function () {
// because span/ul/li has stopPropagation event, div will not be added.
$(document.body).append($("<div>"));
var n = $("div").length;
$("span:eq(1)").text("There are " + n + " divs." +
"Click to add more.");
}).trigger('click'); // trigger the click to start
</script>
</body>
</html>

Tuesday, March 11, 2008

Relationship of Object and Kernel

# Object mixes in the Kernel module, making the built-in kernel functions globally accessible. The instance methods of Object are defined by the Kernel module.


p Kernel.instance_methods(false).length # 42 # Object instance methods
p Kernel.methods(false).length # 65 # Kernel module methods
p Module.instance_methods(false).length # 34 # Module instance methods, Kernel module is instance of Module class.
p Kernel.methods.length # 134

kernel_instance_methods = Kernel.instance_methods(false)
kernel_module_methods = Kernel.methods(false)
module_instance_methods = Module.instance_methods(false)

kernel_methods = [] # 134

Kernel Module include module methods(such as puts/p/gsub...) and module instance methods(such as __id__/__send__/id/send/object_id...), Object class has not defined instance methods, its instance methods are mixed in from Kernel module.

Kernel.methods include three group methods: object instance methods and Kernel module methods and instance methods of class Module.
class A
def self.method1
self.name
end
end
p A.method1
# A
p A.methods(false)
# ["method1"]

Friday, February 15, 2008

Tuesday, September 25, 2007

[learning Python] built-in objects preview

Built-in objects preview

Object type
Example literals/creation


Numbers
3.1415, 1234, 999L, 3+4j


Strings
'spam', "guido's"


Lists
[1, [2, 'three'], 4]


Dictionaries
{'food': 'spam', 'taste': 'yum'}


Tuples
(1,'spam', 4, 'U')


Files
text = open('eggs', 'r').read( )

Sunday, August 05, 2007

prototype javascript library String and Object extend example


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br />\n");
}

Object.extend(String, {
win: doc('this is object of Window ? ' + (this instanceof Window)), // true
size: function (str) {
return arguments.callee.print(str);
}
});

String.size.print = function (arg) {
//doc('String.size.print() = ' + arg.length);
return arg.length;
};

var s = "string size";

doc('String.size = ' + String.size(s));
doc(String.size.print(s));

var wStr = $w('a b c d e f g');
doc(wStr.inspect());
</script>

prototype javascript library Object extend example


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br /><br />\n");
}

Object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}

var o = {
test: 'test it',
sex: 'man',
info: function () {
return this.test + " and " + this.sex;
},
ivk: function () {
return this.info.apply(this); // invoke this.info function
}
}

for(var p in Object) {
doc('Object["' + p + '"] = ' + Object[p]);
}

doc("=============================================================");

Object.extend(Object, o);

for(var p in Object) {
doc('Object["' + p + '"] = ' + Object[p]);
}

alert(Object.ivk());

</script>

Saturday, July 14, 2007

static variable of Javascript


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br />\n");
}

// Define a static variable to hold the running static_var over all calls
// Can't claim static variable with key "var", this is function Object's properties
function doSome (a) {
doSome.static_var ++;
return a + doSome.static_var;
}
doc(typeof doSome); //function Object
doSome.static_var = 0; // var doSome.static_var = 0 will error.
doc(doSome(1)); //2
doc(doSome(1)); //3
doc(doSome(1)); //4
doSome.static_var = 0;
doc(doSome(1)); //2
for (i in doSome)
{
doc(i);
/*static_var
prototype
bind
bindAsEventListener*/
}
</script>

Class Properties
In addition to instance properties and properties of prototypes, JavaScript allows you to define class properties (also known as static properties), properties of the type rather than of a particular object instance. An example of a class property is Number.MAX_VALUE. This property is a type-wide constant, and therefore is more logically located in the class (constructor) rather than individual Number objects. But how are class properties implemented?
Because constructors are functions and functions are objects, you can add properties to constructors. Class properties are added this way. Though technically doing so adds an instance property to a type’s constructor, we’ll still call it a class variable. Continuing our example,

doSome.static_var = 0;

defines a class property of the doSome object by adding an instance variable to the constructor. It is important to remember that static properties exist in only one place, as members of constructors. They are therefore accessed through the constructor rather than an instance of the object.
As previously explained, static properties typically hold data or code that does not depend on the contents of any particular instance. The toLowerCase() method of the String object could not be a static method because the string it returns depends on the object on which it was invoked. On the other hand, the PI property of the Math object (Math.PI) and the parse() method of the String object (String.parse()) are perfect candidates, because they do not depend on the value of any particular instance. You can see from the way they are accessed that they are, in fact, static properties. The isMetallic property we just defined is accessed similarly, as doSome.static_var.

Objects Are Reference Types


Objects Are Reference Types

All JavaScript data types can be categorized as either primitive or reference types.
These two types correspond to the primitive and composite types discussed in Chapter 3.
Primitive types are the primitive data types: number, string, Boolean, undefined, and null.
These types are primitive in the sense that they are restricted to a set of specific values.
You can think of primitive data as stored directly in the variable itself.
Reference types are objects, including Objects, Arrays, and Functions. Because these types can
hold very large amounts of heterogeneous data, a variable containing a reference type does not
contain its actual value. It contains a reference to a place in memory that contains the actual data.

This distinction will be transparent to you the majority of the time.
But there are some situations when you need to pay particular attention
to the implications of these types. The first is when you create two or
more references to the same object. Consider the following example with primitive types:
var x = 10;
var y = x;
x = 2;
alert("The value of y is: " + y);
This code behaves as you would expect. Because x has a primitive type (number),
the value stored in it (10) is assigned to y on the second line. Changing the value
of x has no effect on y because y received a copy of x’s value. The result is shown here:

Now consider similar code using a reference type:
var x = [10, 9, 8];
var y = x;
x[0] = 2;
alert("The value of y's first element is: " + y[0]);
The result might be surprising:

Because arrays are reference types, the second line copies the reference to x’s data into y.
Now both x and y refer to the same data, so changing the value of this data using either
variable is naturally visible to both x and y.

Wednesday, April 18, 2007

区间对象(Range object)

[0..2].each do |i|
puts "i = #{i}"
end

# "0..k" 表示一个区间对象(Range object), 而 "[0..k]"表示一个只有单个区间类型的元素的数组. 例如, 如上运行输出0..2

(0..2).each do |i|
puts "i = #{i}"
end

#上面就会输出3行:
i = 0
i = 1
i = 2

Sunday, March 25, 2007

Converting to object(String,Array)

If an object is converted to an object, it is not modified. If a value of any other type is converted to an object, a new instance of the stdClass built in class is created. If the value was NULL, the new instance will be empty. Array converts to an object with properties named by array keys and with corresponding values. For any other value, a member variable named scalar will contain the value.


<br/>
<?php
$bar = "boo";
$obj = (object) $bar;
var_dump($obj);// object(stdClass)#1 (1) { ["scalar"]=> string(3) "boo" }
echo "<br/>";

$arr = array('x' => 1, 'y' => 2, 'z' => 3);

$obj_arr = (object) $arr;
var_dump($arr); //array(3) { ["x"]=> int(1) ["y"]=> int(2) ["z"]=> int(3) }
var_dump($obj_arr); //object(stdClass)#2 (3) { ["x"]=> int(1) ["y"]=> int(2) ["z"]=> int(3) }
echo "<br/>";

$var = 'x';
echo $obj_arr->x; // 1
echo "<br/>";
echo $obj_arr->$var; // 1
?>

Saturday, March 24, 2007

Object cloning

Creating a copy of an object with fully replicated properties is not always the wanted behavior. A good example of the need for copy constructors, is if you have an object which represents a GTK window and the object holds the resource of this GTK window, when you create a duplicate you might want to create a new window with the same properties and have the new object hold the resource of the new window. Another example is if your object holds a reference to another object which it uses and when you replicate the parent object you want to create a new instance of this other object so that the replica has its own separate copy.
An object copy is created by using the clone keyword (which calls the object's __clone() method if possible). An object's __clone() method cannot be called directly.
$copy_of_object = clone $object;
When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties. Any properties that are references to other variables, will remain references. If a __clone() method is defined, then the newly created object's __clone() method will be called, to allow any necessary properties that need to be changed.


<?php
class SubObject
{
static $instances = 0;
public $instance;

public function __construct() {
$this->instance = ++self::$instances;
}

public function __clone() {
$this->instance = ++self::$instances;
}
}

class MyCloneable
{
public $object1;
public $object2;

function __clone()
{
// Force a copy of this->object, otherwise
// it will point to same object.
$this->object1 = clone($this->object1);
}
}

$obj = new MyCloneable();

$obj->object1 = new SubObject();
$obj->object2 = new SubObject();

$obj2 = clone $obj;


print("Original Object:\n");
print_r($obj);

print("Cloned Object:\n");
print_r($obj2);

?>

Object Interfaces

Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled.
Interface里只要指明有哪些方法,这些方法是在class中实现,interface本身不需要对这些方法处理实现。
Interfaces are defined using the interface keyword, in the same way as a standard class, but without any of the methods having their contents defined.

All methods declared in an interface must be public, this is the nature of an interface.
在Interface里定义的方法必须都是public的,这是Interface的特点。在abstract class 中方法可以是其他二种属性。
implements

To implement an interface, the implements operator is used. All methods in the interface must be implemented within a class; failure to do so will result in a fatal error. Classes may implement more than one interface if desired by separating each interface with a comma.
Note: A class cannot implement two interfaces that share function names, since it would cause ambiguity.
class 实现一个interface用implements操作符,Interface中所有定义的方法在class中都必须实现,这点与abstract class 一样,如果class中有个方法没有实现的话会报错,错误性质与abstract class一样。
可以在同一个class实现多个interface,用“,”隔开interface。


<?php
interface anInterface
{
public function getVar($name, $age);
public function getHtml($html);
}

class ImplementInterface implements anInterface
{
public function getVar($name, $age)
{
echo "name is: {$name}", " age is : {$age}", "<br>";
}
public function getHtml($html)
{
echo "<pre>";
print_r($html);
echo "</pre>";
}
}

$i = new ImplementInterface();
$i->getVar("yu", 29);
$i->getHtml("<a href='#'> test a href </a>");
?>

定义一个interface一般习惯以小写字母开始,命名同变量命名,class 和 abstract class 定义是名字首字母习惯大写开始。

Sunday, February 25, 2007

Properties and Methods of the XMLHTTP Object

The techniques we’ve covered so far use standard browser features for purposes other than that for which they were intended. As such, they lack many features you might want out of RPC-over-HTTP, such as the ability to check HTTP return codes and to specify username/password authentication information for requests. Modern browsers let you do JavaScript RPCs in a much cleaner, more elegant fashion with a flexible interface supporting the needed features missing from the previously discussed hacks.
Internet Explorer 5 and later support the XMLHTTP object and Mozilla-based browsers provide an XMLHTTPRequest object. These objects allow you to create arbitrary HTTP requests (including POSTs), send them to a server, and read the full response, including headers. Table 19-1 shows the properties and methods of the XMLHTTP object.
Table 19-1: Properties and Methods of the XMLHTTP Object
































Property or Method
Description
readyState
Integer indicating the state of the request, either : 0 (uninitialized), 1 (loading), 2 (response headers received), 3 (some response body received), or 4 (request complete).
Onreadystatechange
Function to call whenever the readyState changes.
status
HTTP status code returned by the server (e.g., “200”).
statusText
Full status HTTP status line returned by the server (e.g., “200 OK”).
responseText
Full response from the server as a string.
responseXML
A Document object representing the server's response parsed as an XML document.
abort()
Cancels an asynchronous HTTP request.
getAllResponseHeaders()
Returns a string containing all the HTTP headers the server sent in its response. Each header is a name/value pair separated by a colon, and header lines are separated by a carriage return/linefeed pair.
getResponseHeader(headerName)
Returns a string corresponding to the value of the headerName header returned by the server (e.g., request.getResponseHeader("Set-cookie")).
open(method, url [, asynchronous[, user, password]])
Initializes the request in preparation for sending to the server. The method parameter is the HTTP method to use, for example, GET or POST. The url is the URL the request will be sent to. The optional asynchronous parameter indicates whether send() returns immediately or after the request is complete (default is true, meaning it returns immediately). The optional user and password arguments are to be used if the URL requires HTTP authentication. If no parameters are specified by the URL requiring authentication, the user will be prompted to enter it.
setRequestHeader(name, value)
Adds the HTTP header given by the name (without the colon) and value parameters.
send(body)
Initiates the request to the server. The body parameter should contain the body of the request, i.e., a string containing fieldname=value&fieldname2=value2… for POSTs or the empty string ("") for GETs.


Note
Since the interfaces of these objects as well as their functionality are identical, we’ll arbitrarily refer to both as XMLHTTP objects.

Note
Internet Explorer supports two properties not listed in Table 19-1. The responseBody property holds the server’s response as a raw (undecoded) array of bytes and responseStream holds an object implementing the IStream interface through which you can access the response. Mozilla supports the onload property to which you can set a function that will be called when an asynchronous request completes. However, as these properties are all browser-specific, we don’t discuss them. You can find more information about them on the respective browser vendors’ Web sites.
Some of the properties and methods listed in Table 19-1, such as responseText and getAllResponseHeaders(), won’t be available until the request has completed. Attempting to access them before they’re ready results in an exception being thrown.

Creating and Sending Requests
XMLHTTP requests can be either synchronous or asynchronous, as specified by the optional third parameter to open(). The send() method of a synchronous request will return only once the request is complete, that is, the request completes “while you wait.” The send() method of an asynchronous request returns immediately, and the download happens in the background. In order to see if an asynchronous request has completed, you need to check its readyState. The advantage of an asynchronous request is that your script can go on to other things while it is made and the response received, for example, you could download a bunch of requests in parallel.
To create an XMLHTTP object in Mozilla-based browsers, you use the XMLHttpRequest constructor:
var xmlhttp = new XMLHttpRequest();
In IE, you instantiate a new MSXML XHMLHTTP ActiveX object:
var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
Once you have an XMLHTTP object, the basic usage for synchronous requests is
Parameterize the request with open().
Set any custom headers you wish to send with setRequestHeader().
Send the request with send().
Read the response from one of the response-related properties.
The following example illustrates the concept:
if (document.all)
var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
else
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "http://www.example.com/somefile.html", false);
xmlhttp.send("");
alert("Response code was: " + xmlhttp.status)
The sequence of steps for an asynchronous request is similar:
Parameterize the request with open().
Set any custom headers you wish to send with setRequestHeader().
Set the onreadystatechange property to a function to be called when the request is complete.
Send the request with send().
The following example illustrates an asynchronous request:
if (document.all)
var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
else
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", window.location);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4)
alert("The text of this page is: " + xmlhttp.responseText);
};
xmlhttp.setRequestHeader("Cookie", "FakeValue=yes");
xmlhttp.send("");
When working with asynchronous requests, you don’t have to use the onreadystatechange handler. Instead, you could periodically check the request’s readyState for completion.

POSTs
You can POST form data to a server in much the same way as issuing a GET. The only differences are using the POST method and setting the content type of the request appropriately (i.e., to “application/x-www-form-urlencoded”).
var formData = "username=billybob&password=angelina5";
var xmlhttp = null;
if (document.all)
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
else if (XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
if (xmlhttp)
{
xmlhttp.open("POST", "http://demos.javascriptref.com/xmlecho.php", false);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send(formData);
document.write("<hr>" + xmlhttp.responseText + "<hr>");
}

Thursday, February 22, 2007

Functions as Objects [Javascript 2.0]

JavaScript just about everything that is not primitive data is an object, and functions are no exception. Thus, it is possible to define functions in a much different way than we have seen up until now, by using the keyword new and the Function object. For example, here we define a function and assign it to the variable sayHello. Notice that Function is capitalized, as we are talking about creating an instance of JavaScript’s built-in Function object:
var sayHello = new Function("alert('Hello there');");
Later on we can then use the assigned variable sayHello just like a regular function call:
sayHello();
Because functions are first-class data types, the function can even be assigned to another variable and used by that name instead.
var sayHelloAgain = sayHello;
sayHelloAgain();
To expand the example, we could define a function with a parameter to print out
var sayHello2 = new Function("msg","alert('Hello there '+msg);");
and call it:
sayHello2('Thomas');
The general syntax for the Function() constructor is
var functionName = new Function("argument 1",..."argument n",
"statements for function body");
As we have already seen, functions can have zero arguments, so the actual number of parameters to Function() will vary. The only thing we have to do is pass, as the final argument, the set of statements that are to execute as the body of the function.
If you have coded JavaScript before, you may not have seen this style of function definition and might wonder what its value is. The main advantage of declaring a function using the new operator is that a script can create a function after a document loads.
Note
Since JavaScript 1.2, you can create functions using new anywhere in the script; previously, you could only define them globally and not within a block such as those associated with if statements, loops, or other functions.
Function Literals and Anonymous Functions

As we have seen in the previous section, defining a function using a new operator doesn’t give the function a name. A similar way to define a function without a name and then assign it to something is by using a function literal. Function literals use the function keyword but without an explicit function name.
A simple use of a function literal is
var sayHi = function(name) { alert('Hi my name is '+name); };
sayHi('Fritz');
We assign a function literal to sayHi and can then use it as we would any other function.
The previous example wasn’t particularly compelling, but function literals do have their uses. Their primary use is when creating methods for user-defined objects. A simple example showing function literals used in this manner is presented here. We have defined a function SimpleRobot that is used as an object constructor—a function that creates an object. Within the function we have defined three methods that are assigned function literals.
function SimpleRobot(robotName)
{
this.name = robotName;
this.sayHi = function () { alert('Hi my name is '+this.name); };
this.sayBye = function () { alert('Bye!'); };
this.sayAnything = function (msg) { alert(this.name+' says '+msg); };
}
It is now simple to create an object using the new operator in conjunction with our SimpleRobot constructor function, as shown here:
var fred = new SimpleRobot("Fred");
Invoking the various functions, or, more correctly, methods, is simply a matter of invoking their names, similar to plain function calls:
fred.sayHi();
fred.sayAnything("I don't know what to say");
fred.sayBye();
The result of the previous example is shown here:

You might wonder why not just use the following new-style syntax in the constructor function:
function SimpleRobot(robotName)
{
this.name = robotName;
this.sayHi = new Function ("alert('Hi my name is '+this.name); ");
this.sayBye = new Function ("alert('Bye!'); ");
this.sayAnything = new Function("msg","alert(this.name+' says '+msg);" );
}
The reality is you could, and everything would still operate properly. The only downside to this approach is that it might use substantially more memory, as new function objects are created every time you create a new object.
A similar kind of nameless function doesn’t even get assigned a name at any time. An anonymous function is one that cannot be further referenced after assignment or use. For example, we may want to sort arrays in a different manner than what the built-in sort() method provides; in such cases, we may pass an anonymous function:
var myArray = [2, 4, 2, 17, 50, 8];
myArray.sort( function(x, y)
{
// function statements to do sort
}
);
The creation of an anonymous function is in this case carried out by using a function literal. While the function is accessible to sort() because it was passed a parameter, the function is never bound to a visible name, so it is considered anonymous.

Object-Oriented JavaScript

Object-Oriented JavaScript
Before jumping into the specifics of using JavaScript’s object-oriented features, let’s first understand why an object-oriented approach might be useful. The primary reason is that it allows you to write cleaner scripts, that is, scripts in which data and the code that operates upon it are encapsulated in one place. Consider the Document object. It encapsulates the currently displayed document and presents an interface by which you can examine and manipulate the document in part or as a whole. Can you imagine how confusing document manipulation would be if all of the document-related data and methods were just sitting in the global namespace (i.e., not accessed as document.something but just as something)? What would happen if all of JavaScript’s functionality were so exposed? Even simple programming tasks would be a nightmare of namespace collisions and endless hunting for the right function or variable. The language would be essentially unusable. This is an extreme example, but it illustrates the point. Even smaller-scale abstractions are often best implemented as objects.
But we haven’t really said why it is desirable to have any more advanced object-oriented features in JavaScript than those we’ve already seen (generic Objects with programmer-settable instance properties). The reason is that doing anything but small-scale object-oriented programming with the techniques covered so far would be incredibly laborious. For objects of the same type, you’d be forced to set the same properties and methods of each instance manually. What would be more efficient would be to have a way to specify those properties and methods common to all objects of a certain type once, and have every instance of that type “inherit” the common data and logic. This is the key motivator of JavaScript’s object-oriented features.
Prototype-Based Objects

Java and C++ are class-based object-oriented languages. An object’s properties are defined by its class—a description of the code and data that each object of that class contains. In these languages, a class is defined at compile-time, that is, by the source code the programmer writes. You can’t add new properties and methods to a class at runtime, and a program can’t create new data types while it’s running.
Because JavaScript is interpreted (and therefore has no visible distinction between compile-time and runtime), a more dynamic approach is called for. JavaScript doesn’t have a formal notion of a class; instead, you create new types of objects on the fly, and you can modify the properties of existing objects whenever you please.
JavaScript is a prototype-based object-oriented language, meaning that every object has a prototype, an object from which it inherits properties and methods. When a property of an object is accessed or a method invoked, the interpreter first checks to see if the object has an instance property of the same name. If so, the instance property is used. If not, the interpreter checks the object’s prototype for the appropriate property. In this way the properties and methods common to all objects of that type can be encapsulated in the prototype, and each object can have instance properties representing the specific data for that object. For example, the Date prototype should contain the method that turns the object into a string, because the way it does so is the same for all Date objects. However, each individual Date should have its own data indicating the specific date and time it represents.
The only further conceptual aspect to the way objects work in JavaScript is that the prototype relationship is recursive. That is, an object’s prototype is also an object, and can therefore itself have a prototype, and so on. This means that if a property being accessed isn’t found as an instance property of an object, and isn’t found as a property of its prototype, the interpreter “follows” the prototype chain to the prototype’s prototype and searches for it there. If it still hasn’t been found, the search continues “up” the prototype chain. You might ask, “Where does it end?” The answer is easy: at the generic Object. All objects in JavaScript are ultimately “descendent” from a generic Object, so it is here that the search stops. If the property isn’t found in the Object, the value is undefined (or a runtime error is thrown in the case of method invocation).
Note
The fact that Object is the “superclass” of all other objects explains why we said with confidence in Table 6-2 that the properties and methods listed there are present in every object: because these are exactly the properties and methods of a generic Object!
Now that we’ve explained the theoretical basis for JavaScript’s object-oriented features, let’s see how it translates into implementation. If you’re feeling a bit lost at this point, that’s okay; we’ll reiterate the theory as we cover the concrete details.
Constructors

Object instances are created with constructors, which are basically special functions that prepare new instances of an object for use. Every constructor contains an object prototype that defines the code and data that each object instance has by default.
Note
Before delving any deeper, some commentary regarding nomenclature is appropriate. Because everything in JavaScript except primitive data and language constructs is an object, the term “object” is used quite often. It is important to differentiate between a type of object, for example, the Array or String object, and an instance of an object, for example, a particular variable containing a reference to an Array or String. A type of object is defined by a particular constructor. All instances created with that constructor are said to have the same “type” or “class” (to stretch the definition of class a bit). To keep things clear, remember that a constructor and its prototype define a type of object, and objects created with that constructor are instances of that type.
We’ve seen numerous examples of object creation, for example,
var s = new String();
This line invokes the constructor for String objects, a function named String(). JavaScript knows that this function is a constructor because it is called in conjunction with the new operator.
We can define our own constructor by defining a function:
function Robot()
{

}
This function by itself does absolutely nothing. However, we can invoke it as a constructor just like we did for String():
var guard = new Robot();
We have now created an instance of the Robot object. Obviously, this object is not particularly useful. More information about object construction is necessary before we proceed.
Note
Constructors don’t have to be named with an initial uppercase. However, doing so is preferable because it makes the distinction clear between a constructor (initial uppercase) that defines a type and an instance of a type (initial lowercase).
When a constructor is invoked, the interpreter allocates space for the new object and implicitly passes the new object to the function. The constructor can access the object being created using this, a special keyword that holds a reference to the new object. The reason the interpreter makes this available is so the constructor can manipulate the object it is creating easily. For example, it could be used to set a default value, so we can redefine
our constructor to reflect this ability:
function Robot()
{
this.hasJetpack = true;
}
This example adds an instance property hasJetpack to each new object it creates. After creating an object with this constructor, we can access the hasJetpack property as one would expect:
var guard = new Robot();
var canFly = guard.hasJetpack;
Since constructors are functions, you can pass arguments to constructors to specify initial values. We can modify our constructor again so that it takes an optional argument:
function Robot(needsToFly)
{
if (needsToFly == true)
this.hasJetpack = true;
else
this.hasJetpack = false;
}
// create a Robot with hasJetpack == true
var guard = new Robot(true);
// create a Robot with hasJetpack == false
var sidekick = new Robot();
Note that in this example we could have explicitly passed in a false value when creating the sidekick instance. However, by passing in nothing, we implicitly have done so, since the parameter needsToFly would be undefined. Thus, the if statement fails properly.
We can also add methods to the objects we create. One way to do so is to assign an instance variable an anonymous function inside of the constructor, just as we added an instance property. However, this is a waste of memory because each object created would have its own copy of the function. A better way to do this is to use the object’s prototype.
Prototypes

Every object has a prototype property that gives it its structure. The prototype is a reference to an Object describing the code and data that all objects of that type have in common. We can populate the constructor’s prototype with the code and data we want all of our Robot objects to possess. We modify our definition to the following:
Robot.prototype.hasJetpack = false;
Robot.prototype.doAction = function()
{
alert("Intruders beware!");
};
function Robot(flying)
{
if (flying == true)
this.hasJetpack = true;
}
Several substantial changes have been made. First, we moved the hasJetpack property into the prototype and gave it the default value of false. Doing this allows us to remove the else clause from the constructor. Second, we added a function doAction() to the prototype of the constructor. Every Robot object we create now has both properties:
var guard = new Robot(true);
var canFly = guard.hasJetpack;
guard.doAction();
Here we begin to see the power of prototypes. We can access these two properties (hasJetpack and doAction()) through an instance of an object, even though they weren’t specifically set in the object. As we’ve stated, if a property is accessed and the object has no instance property of that name, the object’s prototype is checked, so the interpreter finds the properties even though they weren’t explicitly set. If we omit the argument to the Robot() constructor and then access the hasJetpack property of the object created, the interpreter finds the default value in the prototype. If we pass the constructor true, then the default value in the prototype is overridden by the constructor adding an instance variable called hasJetpack whose value is true.
Methods can refer to the object instance they are contained in using this. We can redefine our class once again to reflect the new capability:
Robot.prototype.hasJetpack = false;
Robot.prototype.actionValue = "Intruders beware!";
Robot.prototype.doAction = function() { alert(this.actionValue); };

function Robot(flying, action)
{
if (flying == true)
this.hasJetpack = true;
if (action)
this.actionValue = action;
}
We have added a new property to the prototype, actionValue. This property has a default value that can be overridden by passing a second argument to the constructor. If a value for action is passed to the constructor, invoking doAction() will show its value rather than the default ("Intruders beware!"). For example,
var guard = new Robot(true, "ZAP!");
guard.doAction();
results in “ZAP!” being alerted rather than “Intruders beware.”
Dynamic Types
A very important aspect of the prototype is that it is shared. That is, there is only one copy of the prototype that all objects created with the same constructor use. An implication of this is that a change in the prototype will be visible to all objects that share it! This is why default values in the prototype are overridden by instance variables, and not changed directly. Changing them in the prototype would change the value for all objects sharing that prototype.
Modifying the prototypes of built-in objects can be very useful. Suppose you need to repeatedly extract the third character of strings. You can modify the prototype of the String object so that all strings have a method of your definition:
String.prototype.getThirdChar = function()
{
return this.charAt(2);
}
You can invoke this method as you would any other built-in String method:
var c = "Example".getThirdChar(); // c set to 'a'
Class Properties

In addition to instance properties and properties of prototypes, JavaScript allows you to define class properties (also known as static properties), properties of the type rather than of a particular object instance. An example of a class property is Number.MAX_VALUE. This property is a type-wide constant, and therefore is more logically located in the class (constructor) rather than individual Number objects. But how are class properties implemented?
Because constructors are functions and functions are objects, you can add properties to constructors. Class properties are added this way. Though technically doing so adds an instance property to a type’s constructor, we’ll still call it a class variable. Continuing our example,
Robot.isMetallic = true;
defines a class property of the Robot object by adding an instance variable to the constructor. It is important to remember that static properties exist in only one place, as members of constructors. They are therefore accessed through the constructor rather than an instance of the object.
As previously explained, static properties typically hold data or code that does not depend on the contents of any particular instance. The toLowerCase() method of the String object could not be a static method because the string it returns depends on the object on which it was invoked. On the other hand, the PI property of the Math object (Math.PI) and the parse() method of the String object (String.parse()) are perfect candidates, because they do not depend on the value of any particular instance. You can see from the way they are accessed that they are, in fact, static properties. The isMetallic property we just defined is accessed similarly, as Robot.isMetallic.
Inheritance via the Prototype Chain

Inheritance in JavaScript is achieved through prototypes. It is clear that instances of a particular object “inherit” the code and data present in the constructor’s prototype. But what we haven’t really seen so far is that it is also possible to derive a new object type from a type that already exists. Instances of the new type inherit all the properties of their own type in addition to any properties embodied in their parent.
As an example, we can define a new object type that inherits all the capabilities of our Robot object by “chaining” prototypes:
function UltraRobot(extraFeature)
{
if (extraFeature)
this.feature = extraFeature;
}
UltraRobot.prototype = new Robot();
UltraRobot.prototype.feature = "Radar";
The only new concept in this example is setting UltraRobot’s prototype to a new instance of a Robot object. Because of the way properties are resolved via prototypes, UltraRobot objects “contain” the properties of the UltraRobot object as well as those of Robot:
var guard = new UltraRobot("Performs Calculus");
var feature = guard.feature;
var canFly = guard.hasJetpack;
guard.doAction();
The way the interpreter resolves property access in this example is analogous to the resolution that was previously discussed. The object’s instance properties are first checked for a match, then, if none is found, its prototype (UltraRobot) is checked. If no match is found in the prototype, the parent prototype (Robot) is checked, and the process repeats recursively finally to Object.
Overriding Properties

It is often useful to provide specific properties for user-defined objects that override the behavior of the parent. For example, the default value of toString() for objects is "[object Object]". You might wish to override this behavior by defining a new, more appropriate toString() method for your types:
Robot.prototype.toString = function() { return "[object Robot]"; };
Those classes inheriting from Robot might wish to also override the method, for example:
UltraRobot.prototype.toString = function() { return "[object UltraRobot]"; };
This is not only good programming practice, it is useful in case of debugging as well since “object Object” really doesn’t tell you what you are looking at.