JavaScript学习——面向对象的程序设计(二)

JavaScript——创建对象


面向对象的程序设计(一)

Object构造函数或对象字面量都可以用来创建单个对象,但是有缺点:使用同一接口创建很多对象,会产生大量的重复代码。

创建对象的方式大致有以下7种:
1.工厂模式

2.构造函数模式

3.原型模式

4.组合使用构造函数模式和原型模式

5.动态原型模式

6.寄生构造函数模式

7.稳妥构造函数模式



下面一一介绍

1.工厂模式

eg:

function createPerson(name, age, job){			/*驼峰式命名*/
			var o = new Object();		//显示的创建对象
			o.name = name;
			o.age = age;
			o.job = job;
			o.sayName = function(){
				alert(this.name);
			};
			return o ;			//返回该对象
		}
var person1 = createPerson("chenxiaoming",18,"Web dev");		//创建实例不需要用到new
var person1 = createPerson("chenxiaoming",18,"Student"); 


可以无数次调用这个函数,而每次返回一个包含三个属性和一个方法的对象。解决了创建多个相似对象的问题,但却没有解决对象识别的问题(instanceof)


2.构造函数模式

使用构造函数模式重写上面例子

eg:

function Person(name, age, job){		//约定俗成,大写字母开头
			this.name = name;
			this.age = age;
			this.job = job;
			this.sayName = function(){
				alert(this.name);
			};
		}
var person1 = new Person("chenxiaoming",18,"Web dev");
var person2 = new Person("chenxiaoming",18,"Student");


与工厂模式大致相同,不同之处:

a.没有显示的创建对象

b.直接将属性和方法赋给了this对象

c.没有return语句

以这种方式调用构造函数实际上经历以下4个步骤:

a.创建一个新对象

b.将构造函数的作用域赋给新对象(因此this就指向这个新对象)

c.执行构造函数中的代码(为新对象添加属性)

d.返回新对象

person1和person2分别保存着Person的一个不同的实例。这两个对象都有一个constructor(构造函数)属性,该属性指向Person。同时也是Object的实例。

console.log(person1.constructor == Person);		//true
console.log(person2.constructor == Person);		//true

console.log(person1.constructor == Object);		//true
console.log(person2.constructor == Object);		//true

之所以是Object的实例,是因为所有对象均继承自Object。

对象的constructor属性最初是用来标识对象类型的。

可以使用instanceof操作符来检测对象类型。

创建自定义的构造函数可以将它的实例标识为一种特定的类型。

a.将构造函数当作函数

构造函数与其他函数的唯一区别,就在于调用它们的方式不同。

任何函数,只要通过new操作符来调用,那它就可以作为构造函数;而任何函数,如果不通过new操作符来调用,那它跟普通函数也不会有什么两样。

构造函数可以通过以下三种方式调用:

//当做构造函数使用
var person = new Person("chenxiaoming", 18, "Web dev");
person.sayName();				//chenxiaoming
//作为普通函数调用
Person("chenxiaoming", 18, "Web dev");		//添加到window
window.sayName();				//chenxiaoming
//在另一个对象的作用域中调用
var o = new Object();
Person.call(o, "chenxiaomiing", 18, "Web dev");
o.sayName();					//chenxiaoming


b.构造函数的问题

每个方法都要在每个实例上重新创建一遍。上面所创建量person1和person2实例中的方法不是同一个Function实例。

console.log(peson1.sayName == person2.sayName);		//false


以这种方式创建函数,会导致不同的作用域链和标识符解析。

不同实例上的同名函数是不相等的。

通过把函数定义转移到构造函数外部来解决这个问题。

function Person(name, age, job){
			this.name = name;
			this.age = age;
			this.job = job;
			this.sayName = sayName;			//指向函数sayName
		}
function sayName(){
		console.log(this.name);
		}
var person1 = new Person("chenxiaoming", 18, "Web dev");
var person2 = new Person("chenxiaoming", 18, "Student");


在例子中,我们讲sayName()函数的定义转移到了构造函数外部。而在构造函数内部,我们将sayName属性设置成等于全局的sayName函数。

缺点:全局作用域中定义的函数只能被某个对象调用。遇到需要定义多个全局函数的自定义引用类型,封装性就比较差。通过原型模式能比较好的解决构造函数的缺点。





注:原型模式比较重要,在后面花一节整理笔记。








以上笔记整理自《JavaScript权威指南》/《JavaScript高级程序设计(第三版)》,用做个人学习分享


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值