本文介绍了几乎所有关于对象的基本概念,什么是对象,如何创建对象,对象的属性的设置和读取,删除属性的方法,构造函数,对象原型,父类,子类,继承等等。
1.对象
* 对象是一种复合数据类型,它们将多个数据值集中在一个单元中,而且运行使用名字来存取这些值。解释对象的另一种方式是,对象是一个无序的属性集合,每个属性都有自己的名字和值。存储在对象中的已命名的值可以是数字和字符串这样的原始值,也可以是对象。
*/
var o = new Object();
2.对象直接量创建对象
* 对象直接量由属性说明列表构成,列表包含在大括号中,其中的属性说明由逗号隔开。
* 对象直接量中的每个属性说明都由属性名加上冒号和属性值构成。
*/
var zhangsan = {name:”zhangsan”, age:34, married:true};
window.alert(typeof zhangsan); //输出object
3.属性的读取和设置
* 对象的属性通过点号运算符读取和设置。对象的新属性可以通过直接创建。
*/
window.alert(zhangsan.car); //输出undefined
zhangsan.car=”BMW”; //直接赋值
window.alert(zhangsan.car); //输出BMW
4.属性的枚举
* 通过for循环枚举每一个属性,顺序不能保证固定。
* 注意枚举出的是属性名称,并不是属性值。
*/
var values = “”;
for(var v in zhangsan)values += v+”\n”; //枚举每一个属性
window.alert(values);
5.属性的删除使用delete,如delete zhangsan.car
*/
6.构造函数
* 构造函数是具有两个特性的javascript函数:
* (1)它由new 运算符调用;
* (2)传递给它的是一个对新创建的空对象的应用,将该引用作为关键字this的值,而且它还要对新创建的对象进行适当的初始化。
* 记住:构造函数只是初始化对象,并不返回新创建的对象。
*/
function Rectangle(w, h){
this.width = w;
this.height = h;
}
var ret1 = new Rectangle(2, 1);
//注意构造函数是如何使用它的参数来初始化this关键字所引用的对象的属性
7.对象的方法
* 所谓方法,就是通过对象调用的javascript函数。我们知道,函数就是数值,它们所使用的名字没有任何特殊之处,可以将函数赋给任何变量,甚至赋给一个对象的任何属性,那么这个属性就是对象的方法了。
* 在对象的方法体内,关键字this的值就成了调用该方法的对象。
*/
function print(){}
ret1.print = print;
8.关于this的讨论
* 任何一个用作方法的函数都会得到一个额外的实际参数,即调用该函数的对象。由于方法通常是对那个对象执行某种操作,所以要表达函数作用于对象这一事实,最好采用方法的调用语法。
* 如rect.setSize(width, height);
* setSize(rect, width, height);
* 虽然这两行代码对对象rect执行相同的操作,但是第一行代码在表达对象rect是操作的焦点(或者说操作的目标)这一观点时显然清楚得多。
*
* 虽然有区别地对待函数和方法比较有用,但实际上它们之间的差别并不大。回忆一下,函数是存储在变量中的值,而那个变量也不过是全局对象的一个属性。因此,当你调用一个函数时,实际上调用的是全局对象的一个方法。
* 在这样的函数中,关键字this引用的是全局对象。所以函数和方法之间在技术上没有差别,真正的差别在于设计和目的上,方法是用来对this对象进行操作的,而函数通常会是独立的,并不需要使用this对象。
*/
(function f(){
var values = “”;
for(var v in this)values += v + ” “;
window.alert(values);
})(); //返回window对象的所有属性和方法名称
9.原型对象和继承
* javascript每个对象都有原型对象,每个对象都继承原型对象的所有属性。
* 一个对象的原型是由创建并初始化该对象的构造函数定义的。javascript中的所有函数都有prototype属性,它引用了一个对象。虽然原型对象初始化时是空的,
* 但是你在其中定义的任何属性都会被该构造函数创建的所有对象继承。
*
* 构造函数定义了对象的类,并初始化了类中状态变量的属性,如width和height。因为原型对象和构造函数关联在一起,所以类的每个成员都从原型对象继承了相同的属性。
* 这说明原型对象是存放方法和其他常量属性的理想场所。
* 注意,继承是在查询一个属性值时自动发生的。属性并非从原型对象复制到新的对象的,它们只不过看起来像是那些对象的属性。这其中有两点重要的含义。
* 一是使用原型对象可以大量减少每个对象对内存的需求量,因为对象可以继承许多属性。二是即使属性在对象被创建之后才添加到它的原型对象中,对象也能够继承这些属性。
*
* 每个类都有一个原型对象,这个原型对象都具有一套属性。但是实际上却有大量的类实例,每个实例都能继承原型对象的属性。由于一个原型对象能够被多个对象继承,所以javascript
* 必须强化读写属性值之间的不对称性。在读对象o的属性p时,javas会首先检查o是否具有一个名为p的属性。如果o没有这个属性,javascript就会再检查o的原型对象是否具有这个属性。这样才使得以原型为基础的继承机制起作用。
*
* 但是当写一个属性的值时,javascript并不会检查原型对象中是否有这个属性的值。因为,如果允许改变原型对象的这一属性,那就改变了整个对象类的p值,包括其他new出来的对象变量的属性值。
*
* 因此,属性的继承只发生在读属性值时,而不会发生在写属性值时。如果你设置的对象o的属性p是对象o从它的原型对象继承而来的,那么结果就是你直接在对象o中创建了一个新属性p。现在o已经有了一个自己的名为p的属性,它就不会再从它的原型对象继承p的值了。当你读p的值时,java首先查询o的属性。
* 由于它发现了o中定义的p,就不必再查询原型对象,也就不会再发现原型对象中定义的p值了。我们称之为o中的p”遮蔽”了或者说”隐藏”了原型对象中的属性p。
*
* 因为原型对象的属性被一个类的所有对象共享,所以通常只用它们来定义类中所有对象的相同的属性。这使得原型对象适用于方法定义和常量的定义。
*/
10. 实例属性、实例方法、类属性、类方法
* 每个对象都有它自己单独的实例属性的副本。我们说javas中的实例属性是那些在对象中用构造函数创建的或初始化的属性。
*
* 实例方法是由特定对象或实例调用的。实例方法使用了关键字this来引用它们要操作的对象或实例。虽然一个类的任何实例都可以调用实例方法,并不意味着每个对象都像实例属性那样含有自己专有的方法副本。相反,每个实例方法都是由类的所有实例共享的。在javascript中,给类定义一个实例方法,是通过把构造函数的原型对象中的一个属性设置为函数值来实现的。
* 这样,由那个构造函数创建的所有实例都会共享一个已继承的对函数的引用。
*
* 类属性表示在所有类实例中只有一个副本。在javascript中,类属性本质上就是全局变量。但是它们与一个类关联在一起,在javascript的名字空间中拥有一个逻辑位置,这样它们就不会被其他的同名属性覆盖。
* 如Circle.PI=3.14。虽然Circle是一个构造函数,但是由于javascript函数是对象,所以我们可以创建函数的属性,就像创建对象的属性一样。
*
* 类方法与类属性相似。在javascript中,要定义一个类方法,只需要用合适的函数作为构造函数的属性即可。
*/
11. 父类和子类
* 在javascript中,Object类所有类的父类,处于类层次图的最上层。所有的类都继承了Object类的所有方法。
*
* 我们已经学会了对象如何从它们构造函数的原型对象中继承属性,那么它们又是如何继承类Object的属性哪?我们知道,原型对象本身就是一个对象,它是由构造函数Object()创建的。
* 这就意味着原型对象继承了Object.prototype属性。因此,ret1会继承Rectangle.prototype的属性,还会继承Object.prototype的属性。整因为所有对象的prototype属性会继承Object.prototype属性,
* 所以所有javascript子类都继承了Object的所有属性,也即Object类是javascript的根类,处于类层次图的最顶层。
*/
12.使用[]读取和设置对象的属性
* 通常会采用点号运算符访问对象的属性,但是点号后面的属性是标识符。在javascript中,标识符必须逐字输入,它们不是一种数据类型。如果程序中属性是动态的、不确定的,那么我们将无法访问。
* 前面解释过,对象是一群属性的集合,也就是数组。那么可以使用数组访问成员的运算符[]来访问对象的属性。[]中是属性名称,是字符串类型,我们就可以动态的确定对象属性名称了。
*
* 使用[]运算符的对象我们也称之为关联数组。关联数组是一种数据结构,允许你动态地将任意值和任意字符串关联在一起。实际上,javascript对象在内部就是用关联数组实现的。使用点号运算符只是为了是他们看起来更像C++和Java的静态对象而已。
*
* 前面的for/in循环实际上是对数组的操作。
*
* 我们通常意义说的数组是将任何值和非负整数关联在一起的数据结构。
*
* 数组实际上是一个具有额外功能层的对象。如var a = new Array();window.alert(typeof a);输出Object。
*/
13. Object类的属性和方法
* constructor属性表示初始化该对象的构造函数。因此,可以使用该属性来判断对象的类型。
*/
function A(){return “aaaaaaaaa”};
var a = new A();
window.alert(a.constructor); //输出的是A的函数定义
window.alert(a.constructor==A); //结果是true
window.alert(a.constructor()); //输出aaaaaaaaaa
/**
* toString()方法没有任何实际参数,它返回的是一个字符串,该字符串代表了调用它的对象的类型或值。当javascript需要将一个对象转化成字符串时就调用这个对象的toString方法。
* 例如,当用运算符”+”把一个字符串和一个对象连接到一起时,或者把一个对象传递给alert()或document.write()方法时,就会调用toString()方法。
*/