Object是编程中的重要话题。严格来说,讨论Object时,需要区分Object和Object Instance两个概念。
function Person(){ this.name = 'Sean'; this.age = 30; }
上面的例子定义了一个叫做'Person'的Object,它有两个属性'name'和'age'。没错,它看起来像是一个function(函数),但这的确是最基本的定义一个对象的方法。
我们定义一个对象是为了使用它,这需要一个对象实例(Object Instance)。可以通过new
操作符来得到一个Object Instance,比如:
var person_a = new Person(); person_a.name = 'Name 1'; var person_b = new Person(); alert(person_a.name); alert(person_b.name); alert(person_a['name']);
上面的例子不仅展示了如何得到一个对象实例(Object Instance),同时也展示了如何访问对象的属性。访问对象的属性可以通过 .
或[]
操作符来实现,两者是等价的。通过[]
的方式,使得我们可以动态决定属性名,或者使用不符合JavaScript变量命名规定的属性名。比如下面的例子:
person_a['office address'] = 'some address'; var name = 'home address'; person_a[name] = 'some address 2'; alert(person_b[name]); // undefined
上面的例子也表明,一个Object Instance除了拥有它原有定义的属性外,是可以添加新的属性的。这些新添加的属性只存在于这个Object Instance本身,不影响其它的Object Instance。
JavaScript允许在没有Object的定义的情况下,直接得到一个Object Instance。
var person_c = {name:'Zhang San', age:23}; alert(person_c.name);
从效果上来说,上面例子中的person_c和之前例子中的person_a或者person_b并没有太大区别,写法上却更简单。
比如上面Person的对象实例person_a,我们访问它的属性'phone'的话,因为该属性不存在,所以会返回 undefined。实际上访问对象属性的过程要比这个复杂。其过程可以描述如下:
function getObjectAttribute(obj, name){ var p = obj; while(p!=null){ if(p.hasOwnProperty('name')) return p.name; p = obj.__proto__; } return null; }
上面程序片段中,hasOwnProperty
表示对象本身是否定义了这个属性,如果没有定义,则试图沿着一个特殊的属性proto
逐级向上查找要访问的属性名。
聪明的你也许会想到,这似乎有点对象继承的意思了。没错,这正是JavaScript中实现对象继承的关键。
上面提到,在得到一个对象实例的时候,实际上有两种方法:new
或者{}
的方式。对于 {}
的方式,它的proto属性无所从来(实际上是一个Object对象的实例)。对于new
的方式,proto属性会被赋值为对象定义的 prototype 属性。用代码可以表示如下
var person_a = new Peron(); person_a.__proto__ = Person.prototype; // 会由JavaScript Engine 自动执行
至此,一种实现对象继承的方法也就出来了。
对象定义的prototype属性和{}
得到的对象实例的proto
属性的默认值是Object对象的一个实例。据此,我们也许可以给所有的对象都添加一个”全局"方法。下面的代码在Firefox中运行通过,所有的对象实例都有了一个println()
方法。
Object.prototype.println = function() { alert('I am here'); }; function Person(){ this.name = 'abc'; } var p = new Person(); p.println(); var o = {name:'Sean', age:30}; o.println();
由于JavaScript中,函数(function)其实是Function Object的实例,因而对象的方法和属性就其本质而言没有区别。
function Person(fname, sname){ this.firstName = fname, this.secondName = sname; this.fullName = function(){ return this.fname + ', ' + this.secondName; }; } var person = new Person('Sean', 'Zhang'); alert(this.fullName());
上面的例子定义了对象的方法'fullName',同时也展示了如何初始化对象——利用函数的参数。
上面很多代码中都出现了this
这个关键字,它表示访问该属性或方法的对象实例。看下面的例子:
function outside_fullName(){ return this.fname + ', ' + this.secondName; }; function Person(fname, sname){ this.firstName = fname, this.secondName = sname; this.fullName = outside_fullName; } var person = new Person('Sean', 'Zhang'); alert(this.fullName());
这个例子和之前的例子实际效果相同,但却把方法的定义放在了对象定义的外部。虽然在定义方法时还不知道对象是谁,但却通过this这个特殊关键字来表示发起调用的对象实例。
function Person (name) { this.name = name; } function Employee(title){ this.title = title; } Employee.prototype = new Person();
function Employee(name, title){ Person.call(this, name); this.title = title; }
利用这种方法,可以实现多继承。