理解JavaScript的一些基本概念
看JavaScript的时候,觉得有些东西怪怪的,和一般的编程语言还是有些差别,不太习惯一些写法,今天看了一篇文章,小有收获。(http://www.cnblogs.com/leadzen/archive/2008/02/25/1073404.html)
一、数据类型
任何一个JavaScript的标识、常量、变量和参数都只是unfined, null, bool, number, string, object 和 function类型中的一种,也就typeof返回值表明的类型。除此之外没有其他类型了。
object就是对象的类型。在JavaScript中不管多么复杂的数据和代码,都可以组织成object形式的对象。但JavaScript却没有 “类”的概念!
如下代码:
var life = {};
for (life.age = 1 ; life.age <= 3 ; life.age ++ )
{
switch (life.age)
{
case 1 : life.body = " 卵细胞 " ;
life.say = function (){alert( this .age + this .body)};
break ;
case 2 : life.tail = " 尾巴 " ;
life.gill = " 腮 " ;
life.body = " 蝌蚪 " ;
life.say = function (){alert( this .age + this .body + " - " + this .tail + " , " + this .gill)};
break ;
case 3 : delete life.tail;
delete life.gill;
life.legs = " 四条腿 " ;
life.lung = " 肺 " ;
life.body = " 青蛙 " ;
life.say = function (){alert( this .age + this .body + " - " + this .legs + " , " + this .lung)};
break ;
};
life.say();
};
对象不是固定的,可以动态的添加属性和方法。定义变量时也不需要指定变量的类型等信息,可以直接赋值任何类型。
二、函数
JavaScript的代码就只有function一种形式,function就是函数的类型。也许其他编程语言还有procedure或 method等代码概念,但在JavaScript里只有function一种形式。当我们写下一个函数的时候,只不过是建立了一个function类型 的实体而已。请看下面的程序:
{
alert( " hello " );
};
alert( typeof (myfunc));
这个代码运行之后可以看到typeof(myfunc)返回的是function。以上的函数写法我们称之为“定义式”的,如果我们将其改写成下面的“变量式”的,就更容易理解了:
{
alert( " hello " );
};
alert( typeof (myfunc));
函数也是对象,可以为函数添加相应的属性和方法(函数)。
这些属性可以是简单类型,可以是对象,也可以是其他函数。也就是说,函数具有对象的全部特征,你完全可以把函数当对象来用。
看下面的代码:
{
with (arguments.callee)
alert(author + " : " + poem);
};
Sing.author = " 李白 " ;
Sing.poem = " 汉家秦地月,流影照明妃。一上玉关道,天涯去不归

Sing();
Sing.author = " 李战 " ;
Sing.poem = " 日出汉家天,月落阴山前。女儿琵琶怨,已唱三千年

Sing();
三、object
JavaScript里的函数和对象既有对象的特征也有数组的特征。这里的数组被称为“字典”,一种可以任意伸缩的名称值对儿的集合。其实, object和function的内部实现就是一个字典结构,但这种字典结构却通过严谨而精巧的语法表现出了丰富的外观。可以在需要的时候,自由选择用对象还是数组来解释和处理问题。只要善于把握 JavaScript的这些奇妙特性,就可以编写出很多简洁而强大的代码来。
anObject.aProperty = " Property of object " ; // 对象的一个属性
anObject.aMethod = function (){alert( " Method of object " )}; // 对象的一个方法
// 主要看下面:
alert(anObject[ " aProperty " ]); // 可以将对象当数组以属性名作为下标来访问属性
anObject[ " aMethod " ](); // 可以将对象当数组以方法名作为下标来调用方法
for ( var s in anObject) // 遍历对象的所有属性和方法进行迭代化处理
alert(s + " is a " + typeof (anObject[s]));
同样对于function类型的对象也是一样:
aFunction.aProperty = " Property of function " ; // 函数的一个属性
aFunction.aMethod = function (){alert( " Method of function " )}; // 函数的一个方法
// 主要看下面:
alert(aFunction[ " aProperty " ]); // 可以将函数当数组以属性名作为下标来访问属性
aFunction[ " aMethod " ](); // 可以将函数当数组以方法名作为下标来调用方法
for ( var s in aFunction) // 遍历函数的所有属性和方法进行迭代化处理
alert(s + " is a " + typeof (aFunction[s]));
四、“this”指针
JavaScript 中也有this,但这个this却与C++、C#或Java等语言的this不同。一般编程语言的this就是对象自己,而 JavaScript的this却并不一定!同一个函数可以从不同的角度来调用,this并不一定是函数本身所属的对象。this只是在任意对象和 function元素结合时的一个概念,是种结合比起一般对象语言的默认结合更加灵活,显得更加超然和洒脱。
看下面的代码:
{
alert( " I'm " + this .name + " of " + typeof ( this ));
};
WhoAmI(); // 此时是this当前这段代码的全局对象,在浏览器中就是window对象,其name属性为空字符串。输出:I'm of object
var BillGates = {name: " Bill Gates " };
BillGates.WhoAmI = WhoAmI; // 将函数WhoAmI作为BillGates的方法。
BillGates.WhoAmI(); // 此时的this是BillGates。输出:I'm Bill Gates of object
var SteveJobs = {name: " Steve Jobs " };
SteveJobs.WhoAmI = WhoAmI; // 将函数WhoAmI作为SteveJobs的方法。
SteveJobs.WhoAmI(); // 此时的this是SteveJobs。输出:I'm Steve Jobs of object
WhoAmI.call(BillGates); // 直接将BillGates作为this,调用WhoAmI。输出:I'm Bill Gates of object
WhoAmI.call(SteveJobs); // 直接将SteveJobs作为this,调用WhoAmI。输出:I'm Steve Jobs of object
BillGates.WhoAmI.call(SteveJobs); // 将SteveJobs作为this,却调用BillGates的WhoAmI方法。输出:I'm Steve Jobs of object
SteveJobs.WhoAmI.call(BillGates); // 将BillGates作为this,却调用SteveJobs的WhoAmI方法。输出:I'm Bill Gates of object
WhoAmI.WhoAmI = WhoAmI; // 将WhoAmI函数设置为自身的方法。
WhoAmI.name = " WhoAmI " ;
WhoAmI.WhoAmI(); // 此时的this是WhoAmI函数自己。输出:I'm WhoAmI of function
({name: " nobody " , WhoAmI: WhoAmI}).WhoAmI(); // 临时创建一个匿名对象并设置属性后调用WhoAmI方法。输出:I'm nobody of object
五、JavaScript对象表示法(JavaScript Object Notation,JSON)
JSON的形式就是用大括“{}”号包括起来的项目列表,每一个项目间并用逗号“,”分隔,而项目就是用冒号“:”分隔的属性名和属性值。这是典型的字典 表示形式,也再次表明了 JavaScript里的对象就是字典结构。不管多么复杂的对象,都可以被一句JSON代码来创建并赋值。
创建一个没有任何属性的对象:
创建一个对象并设置属性及初始值:
创建一个对象并设置属性和方法:
创建一个更复杂的对象,嵌套其他对象和对象数组等:
{
name: " Microsoft " ,
product: " softwares " ,
chairman: {name: " Bill Gates " , age: 53 , Married: true },
employees: [{name: " Angel " , age: 26 , Married: false }, {name: " Hanson " , age: 32 , Marred: true }],
readme: function () {document.write( this .name + " product " + this .product);}
};
除JSON外,在JavaScript中我们可以使用new操作符结合一个函数的形式来创建对象。例如:
var anObj = new MyFunc(); // 使用new操作符,借助MyFun函数,就创建了一个对象
JavaScript的这种创建对象的方式可真有意思,如何去理解这种写法呢?
其实,可以把上面的代码改写成这种等价形式:
var anObj = {}; // 创建一个对象
MyFunc.call(anObj); // 将anObj对象作为this指针调用MyFunc函数
我们就可以这样理解,JavaScript先用new操作符创建了一个对象,紧接着就将这个对象作为this参数调用了后面的函数。其实,JavaScript内部就是这么做的,而且任何函数都可以被这样调用!
六、prototype
prototype 源自法语,软件界的标准翻译为“原型”,代表事物的初始形态,也含有模型和样板的意义。 JavaScript的所有function类型的对象都有一个prototype属性。这个prototype属性本身又是一个object类型的对 象,因此我们也可以给这个prototype对象添加任意的属性和方法。
在构造函数的prototype上定义的所有属性和方法,都是可以通过其构造的对象直接访问和调用的。也可以这么说,prototype提供了一群同类对象共享属性和方法的机制。
代码:
{
this .name = name; // 设置对象属性,每个对象各自一份属性数据
};
Person.prototype.SayHello = function () // 给Person函数的prototype添加SayHello方法。
{
alert( " Hello, I'm " + this .name);
}
var BillGates = new Person( " Bill Gates " ); // 创建BillGates对象
var SteveJobs = new Person( " Steve Jobs " ); // 创建SteveJobs对象
BillGates.SayHello(); // 通过BillGates对象直接调用到SayHello方法
SteveJobs.SayHello(); // 通过SteveJobs对象直接调用到SayHello方法
alert(BillGates.SayHello == SteveJobs.SayHello); // 因为两个对象是共享prototype的SayHello,所以显示:true
可以随时给原型对象动态添加新的属性和方法,从而动态地扩展基类的功能特性。这在静态对象语言中是很难想象的。
代码:
{
this .name = name;
};
Person.prototype.SayHello = function () // 建立对象前定义的方法
{
alert( " Hello, I'm " + this .name);
};
var BillGates = new Person( " Bill Gates " ); // 建立对象
BillGates.SayHello();
Person.prototype.Retire = function () // 建立对象后再动态扩展原型的方法
{
alert( " Poor " + this .name + " , bye bye! " );
};
BillGates.Retire(); // 动态扩展的方法即可被先前建立的对象立即调用
事实上,如果在JavaScript内置的那些如Object和Function等函数的prototype上添加些新的方法和属性,就能扩展JavaScript的功能。
比如微软的ASP.NET AJAX,就给这些内置函数及其prototype添加了大量的新特性,从而增强了JavaScript的功能。
下面是一段摘自MicrosoftAjax.debug.js中的代码:
if (arguments.length !== 0 ) throw Error.parameterCount();
return this .replace( / ^/s+|/s+$ / g, '' );
}