日期:2014-05-16 浏览次数:20566 次
1. 理解JavaScript的对象
??? 面向对象的的语言都有类的概念,类抽象了对象共有的属性和行为,根据类可以创建不同的对象。
??? 可是Javascript中没有类的概念,因此它的对象也与基于类的语言中的对象有所不同。
??? ECMA-262把对象定义为:"无序属性的集合",其属性可以是基本值,对象,或者函数。(严格来讲,这就相当于说对象是一组没有特定顺序的值)
??? JavaScript中每个对象都是基于一个引用类型创建的,包括JavaScript的原生类型(如Array,Date等),也可以是开发人员自定义的类型。
?
2. 创建对象
??? 1) 利用Object类型
??????? 创建自定义对象最简单的方法就是创建一个Object的实力,然后再为它添加属性和行为,如下:
???????????
var person = new Object(); person.name = "anser"; //属性 person.age = 22; person.job = "Software Engineer"; person.sayName = function() { //行为 alert(this.name); }
??? ?2) 工厂模式
???????? 使用Object类型创建不同类型的对象的缺点:使用同一个接口创建很多对象,会产生很多重复的代码。如上面,分别创建person1,person2......
??????? 因此使用工厂模式,封装特定接口创建对象的细节,上面示例修改如下:
?
function createPerson(name, age, job) { var person = new Object(); person.name = name; person.age = age; person.job = job; person.sayName = function() { alert(this.name); } return person; }
??????? 使用工厂模式虽然解决了创建多个相似对象的问题,可是却没有解决对象识别的问题(及怎么样知道一个对象的类型:通过 instanceof 操作符)。
? 3) 构造函数模式
??????? ECMAScript中的构造函数可用来创建特定类型的对象。像Object,Array这样的原生构造函数,在运行时会自动出现在执行环境中。
??????? 此外,也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。改写以上的例子如下:
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function() { alert(this.name); } } Person person1 = new Person("anser", 22, "Software Engineer"); Person person2 = new Person("xhc", 22, "Player");
????????注意到构造函数模式和工厂模式的不同:
??????????? a. 没有显示地创建对象,在工厂模式中创建了新的Object对象;
??????????? b. 直接将属性和方法赋给了this对象,在工厂模式中赋给了新创建的Object对象;
??????????? c. 没有return语句, 在工厂模式中在工厂方法中返回显示创建的Object对象。
??????
??????? 要创建新的Person对象,使用new操作符,以这种方式调用构造函数实际上会经历一下4个步骤:
??????????? a. 创建一个新对象;
??????????? b. 将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
??????????? c. 执行构造函数中的代码(为这个新对象添加属性);
??????????? d. 返回新对象。
??????? 通过构造函数创建的对象都有一个constructor(构造函数)属性,指向Person构造函数:
????????
alert(person1.constructor == Person); //true; alert(person2.consturcotr == Person); //ture;
?
??????? 但是检测对象类型还是使用instanceof操作符更可靠一些(因为在后面会介绍到,对象的构造函数不一定是这个类型的构造函数)。
alert(person1 instanceof Object); //true; 所有的对象均继承自Objec alert(person1 instanceof Person); //true;
?
??????? 使用构造函数,可以将它的实例标识为一种特定的类型,这正是构造函数模式胜过工厂模式的地方。
?理解构造函数:
??????? 1. 构造函数名首字母尽量大写,主要为了区分ECMAScript中的其他函数,因为构造函数本身也是函数,只不过可以用来创建对象而已。
??????? 2. 构造函数与其他函数的唯一区别,就在于调用它们的方式不同。任何函数通过new操作符来调用,那它就可以作为构造函数。
??????????? 如上面的构造函数Person:
//当作构造函数使用 Person person = new Person("anser", 22, "Software Engineer"); person.sayName(); //anser //作为普通函数使用 Person("name1", 27, "job"); //添加到window,此时调用函数Person的作用域为window对象 window.sayName(); //name1 //在另一个对象的作用域中调用 Object o = new Object(); o.Person("object", 1, "test"); o.sayName(); //object
?
??????? 3. 构造函数的问题
??????????? 使用构造函数的缺点:就是每个方法都要在每个对象的实例上重新创建一遍。
??????????? 如前面例子中的person1和person2对象都有一个名为sayName()的方法,但那两个方法不是同一个Function的实例。
??????????? ECMAScript中函数也是对象,因此每定义一个函数,也就是实例化了一个对象。
??????????? 因此上面的构造函数实际相当于:
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = new Function(" alert(this.name);") ; //与声明函数在逻辑上是等价的 } alert(person1.sayName == person2.sayName); //false