Object Type
创建Object实例
创建Object实例的方法有两种
Object构造函数
var person = new Object ();
person . name = "Nicholas" ;
person . age = 29 ;
对象字面量
var person = {
name : "Nicholas" , // 用逗号隔开各个属性
age : 29 // 此处无逗号
};
使用对象字面量时,属性名可以是字符串,如下
var person = {
"name" : "Nicholas" ,
"age" : 29 ,
5 : true
};
此处name,age,5都会作为字符串处理
如下的定义方式也是正确的
var person = {}; //same as new Object()
person . name = "Nicholas" ;
person . age = 29 ;
通过对象字面量定义对象时,不会调用Object构造函数
另外,对象字面量也是向函数传递大量可选参数的首选方法
function displayInfo ( args ) {
var output = "" ;
if ( typeof args . name == "string" ){
output += "Name: " + args . name + "\n" ;
}
if ( typeof args . age == "number" ) {
output += "Age: " + args . age + "\n" ;
}
alert ( output );
}
displayInfo ({
name : "Nicholas" ,
age : 29
});
displayInfo ({
name : "Greg"
});
上面的代码中,我们先定义了一个displayInfo函数,然后两次调用该函数,两次调用所传递的参数都不同
上面的方式最适合传递若干可选参数的情形。
访问对象的属性
访问对象的属性可以有两种方式,除了点表示法 ,还可以使用方括号表示法 。不过属性名应该以字符串的形式放在方括号中
如下
alert ( person [ "name" ]); //"Nicholas"
alert ( person . name ); //"Nicholas"
以上两种方法没有区别,但方括号语法的优点是可以通过变量的方式访问,如下
var propertyName = "name" ;
alert ( person [ propertyName ]); //"Nicholas"
如果属性名中包含导致语法错误的字符,或者关键字,保留字,则可以使用方括号表示法,如下
person [ "first name" ] = "Nicholas" ;
除了特别情况,一般推荐使用点表示法
Function Type
javascript中的函数也是对象,函数名是指向函数对象的指针,所以,javascript中的重载其实只是
函数名指向另一个函数而已。
定义函数可以有以下三种方式
using function-declaration syntax
function sum ( num1 , num2 ) {
return num1 + num2 ;
}
using a function expression
var sum = function ( num1 , num2 ){
return num1 + num2 ;
};
using the Function constructor
这种方式不推荐使用。这种语法能很好解释函数时一种对象。
var sum = new Function ( "num1" , "num2" , "return num1 + num2" ); //not recommended
以上表达式中,Function的最后一个参数是函数体,其他为函数参数。
由于函数名只是函数对象的指针,那么一个函数可以有多个名字(一个函数对象可以有多个函数指针),如下
function sum ( num1 , num2 ){
return num1 + num2 ;
}
alert ( sum ( 10 , 10 )); //20
var anotherSum = sum ;
alert ( anotherSum ( 10 , 10 )); //20
sum = null ;
alert ( anotherSum ( 10 , 10 )); //20
No Overloading (没有重载)
看如下例子
function addSomeNumber ( num ){
return num + 100 ;
}
function addSomeNumber ( num ) {
return num + 200 ;
}
var result = addSomeNumber ( 100 ); //300
我们貌似对addSomeNumber(num)进行了重载,然后进行调用,最后调用到了第二个函数,
其实此处没有重载,下面代码等同于上面代码,
var addSomeNumber = function ( num ){
return num + 100 ;
};
addSomeNumber = function ( num ) {
return num + 200 ;
};
var result = addSomeNumber ( 100 ); //300
很明显,所谓的”重载”,只是函数对象被重新定义了而已,而非重载。
Function Declarations versus Function Expressions (函数声明和函数表达式)
如下代码
alert ( sum ( 10 , 10 ));
function sum ( num1 , num2 ){
return num1 + num2 ;
}
函数sum声明在调用之后,但是能正常执行。
Function Declarations 与 Function Expressions 之间有一个区别,就是Function Declarations 中有函数声明提升(function declaration hoisting.) 在代码执行之前,解析器会将函数声明添加到执行环境,并放到源代码树的顶部。
再看如下代码,
alert ( sum ( 10 , 10 )); //unexpected identifi er
var sum = function ( num1 , num2 ){
return num1 + num2 ;
};
如上代码使用函数表达式,则会出错。
Functions as Values
函数作为值,可以作为值传入给某个函数,也可以作为某个函数的返回值
(This means it’s possible not only to pass a function into another
function as an argument but also to return a function as the result of another function.)
pass a function into another function
function callSomeFunction ( someFunction , someArgument ){
return someFunction ( someArgument );
}
function add10 ( num ){
return num + 10 ;
}
var result1 = callSomeFunction ( add10 , 10 );
alert ( result1 ); //20
function getGreeting ( name ){
return "Hello, " + name ;
}
var result2 = callSomeFunction ( getGreeting , "Nicholas" );
alert ( result2 ); //"Hello, Nicholas"
上面代码定义函数callSomeFunction,它能接收2个参数,一个是某个函数指针x,一个是函数x的参数,
然后在callSomeFunction执行函数x 。
return a function as the result of another function
以下函数返回结果是一个函数,这个返回函数主要是对object1,object2两个对象的某个属性进行比较。
该函数常用于数组的排序
function createComparisonFunction ( propertyName ) {
return function ( object1 , object2 ){
var value1 = object1 [ propertyName ];
var value2 = object2 [ propertyName ];
if ( value1 < value2 ){
return - 1 ;
} else if ( value1 > value2 ){
return 1 ;
} else {
return 0 ;
}
};
}
var data = [{ name : "Zachary" , age : 28 }, { name : "Nicholas" , age : 29 }];
data . sort ( createComparisonFunction ( "name" ));
alert ( data [ 0 ]. name ); //Nicholas
data . sort ( createComparisonFunction ( "age" ));
alert ( data [ 0 ]. name ); //Zachary
Function Internals (函数内部属性)
Two special objects exist inside a function: arguments and this。
arguments
arguments 对象代表传递给函数的参数数组,它也是一个对象,它有一个特殊的属性: callee
callee此处其实也是个函数,但是在javascript中函数也是对象,所以此处也称为属性。
callee指向拥有arguments对象的对象( the arguments object
also has a property named callee, which is a pointer to the function that owns the arguments
object)
看如下递归例子
function factorial ( num ){
if ( num <= 1 ) {
return 1 ;
} else {
return num * factorial ( num - 1 )
}
}
当函数指针赋值给另一个变量时,上面函数内部与名字factorial耦合则会出现问题
为了解决这个问题,可以用如下方式
function factorial ( num ){
if ( num <= 1 ) {
return 1 ;
} else {
return num * arguments . callee ( num - 1 )
}
}
var trueFactorial = factorial ;
factorial = function (){
return 0 ;
};
alert ( trueFactorial ( 5 )); //120
alert ( factorial ( 5 )); //0
this
某个全局环境中的函数,它的this指针等同于window
某个对象内部的函数的this,它指向这个对象本身。
如下:
window . color = "red" ;
var o = { color : "blue" };
function sayColor (){
alert ( this . color );
}
sayColor (); //"red"
o . sayColor = sayColor ;
o . sayColor (); //"blue"
ECMAScript还规范化了另一个函数对象的属性:caller。它指向调用当前函数的函数的引用,如果当前函数时在全局作用域中,
则它的caller属性为null。如下代码:
function outer (){
inner ();
}
function inner (){
alert ( inner . caller );
}
outer ();
上述代码将在警告框显示outer()函数的源代码
为了实现更松散的耦合,可以如下
function outer (){
inner ();
}
function inner (){
alert ( arguments . callee . caller );
}
outer ();
Function Properties and Methods
Each function has two properties: length and prototype
.length属性返回函数的参数个数,prototype不在这里讲解。
function sayName ( name ){
alert ( name );
}
function sum ( num1 , num2 ){
return num1 + num2 ;
}
function sayHi (){
alert ( "hi" );
}
alert ( sayName . length ); //1
alert ( sum . length ); //2
alert ( sayHi . length ); //0
There are two additional methods for functions: apply() and call().
apply(),call()的基本作用都是调用函数,如下
function sum ( num1 , num2 ){
return num1 + num2 ;
}
function callSum1 ( num1 , num2 ){
return sum . apply ( this , arguments ); //passing in arguments object
}
function callSum2 ( num1 , num2 ){
return sum . apply ( this , [ num1 , num2 ]); //passing in array
}
alert ( callSum1 ( 10 , 10 )); //20
alert ( callSum2 ( 10 , 10 )); //20
function sum ( num1 , num2 ){
return num1 + num2 ;
}
call()方法需要罗列出具体每个参数,apply()方法只需使用arguments。
function callSum ( num1 , num2 ){
return sum . call ( this , num1 , num2 );
}
alert ( callSum ( 10 , 10 )); //20
apply(),call()最强大的作用并不在于传递参数,调用函数,而是扩充函数的作用域,如下
window . color = "red" ;
var o = { color : "blue" };
function sayColor (){
alert ( this . color );
}
sayColor (); //red
sayColor . call ( this ); //red
sayColor . call ( window ); //red
sayColor . call ( o ); //blue
Running sayColor.call(o) switches the context of the function such that this points to o,
resulting in a display of “blue”.
使用apply() , call() 扩大函数的作用域的好处是,对象与方法不需要有任何耦合关系。
ECMAScript 5 定义了一个bind()方法,The bind() method creates a new
function instance whose this value is bound to the value that was passed into bind()
如下
window . color = "red" ;
var o = { color : "blue" };
function sayColor (){
alert ( this . color );
}
var objectSayColor = sayColor . bind ( o );
objectSayColor (); //blue
另外
函数对象调用toLocaleString() toString() valueOf() 将返回函数代码