JavaScript面向对象的程序设计

笔记放在Github上,点击访问下载


创建对象

创建对象的四种模式:工厂模式、构造函数模式、原型模式、组合使用构造函数和原型模式


  • 工厂模式
function sayName(){
	return this.name;
}
function createPerson(name,age,gender){
	var o = new Object();
	o.name = name;
	o.age = age;
	o.gender = gender;
	/*o.sayName = function(){
		return this.name;
	};*/
	o.sayName = sayName;
	return o;
	/*return {
		name:name,
		age:age,
		gender:gender,
		sayName:function(){
			return this;
		}
	}*/
}
var o1 = createPerson('Tom',18,'男');
var o2 = createPerson('Mary',16,'女');
console.log(o1.constructor);//[Function: Object]
console.log(o2.constructor);//[Function: Object]
console.log(o1.sayName===o2.sayName);//false->true

当在对象中定义sayName时,相当于每次创建一个新对象,都会在内存中重新开辟一个新的空间存放sayName方法,所以o1.sayName===o2.sayNamefalse,因为两者的sayName方法内存地址不同。而通过声明函数声明的sayName,在内存中的内存地址不变,所以返回true

工厂模式的问题:工厂模式创建的所有对象都是Object类型,且工厂模式每创建一个对象,其对象的方法就会开辟一个新的内存空间,耗费内存资源。


  • 构造函数模式
function sayName(){
	return this.name;
}
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
/*this.sayName = function(){
alert(this.name);
} */
this.sayName = sayName;
}
var p1 = new Person("terry",11,"boss");
var p2 = new Person("larry",12,"daBoss");
console.log(p1.constructor);//[Function: Person]
console.log(p1.sayName===p2.sayName);//false->true

使用new关键字调用构造函数创建对象的步骤:

  1. 创建一个新对象
  2. 将构造函数的作用域赋给新对象(this指向这个新对象)
  3. 执行构造函数中的代码
  4. 返回新对象

构造函数的问题:每个方法都需要在每个实例上重新创建一遍,但是毫无必要。可以通过在全局作用域中声明一个函数,然后将引用传递给对象中的函数属性,但是这样会导致全局函数过多,体现不了对象的封装性。


  • 原型模式

原型语法:
创建了自定义的构造函数之后,会同时创建它的prototype对象,其原型对象默认会取得constructor属性;当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。(指向的是原型对象而不是构造函数)

function Person(){}
Person.prototype.name = 'z';
Person.prototype.friends = [];
Person.prototype.sayName = function(){
	console.log(this.name);
};
var p1 = new Person();
console.log(p1.name);//z
var p2 = new Person();
console.log(p2.name);//z
p1.friends.push('tom');
console.log(p1.friends);//[ 'tom' ]
console.log(p2.friends);//[ 'tom' ]
console.log(p1.sayName===p2.sayName);//true

更简单的原型语法:
将原型对象设置为等于一个以对象字面量形式创建的新对象,实例对象使用效果相同,但是原型中的constructor属性不再指向Person。因为每创建一个函数,就会同时创建它的prototype对象,这个对象也自动获得constructor属性。这里重写了prototype对象因此新创建的原型中constructor属性指向就不再是Person,所以往Person的父级寻找,最后指向Object

function Person(){}
Person.prototype={
	name:'yoyo',
	friends:[],
	sayName:function(){
		console.log(this.name);
	}
}

原型对象的问题:所有实例在默认情况下都将取得相同的属性值,这种共享对于函数来说非常合适,但是包含引用数据类型的值就不太好


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

构造函数用于定义实例属性,原型模式用于定义方法和共享属性。

function Person(name,age){
	this.name = name;
	this.age = age;
	this.friends = [];
}
Person.prototype = {
	constructor:Person,
	sayName:function(){
		return this.name;
	}
};
var p1 = new Person('Tom',18);
var p2 = new Person('Jerry',16);
p2.friends.push('Mary');
console.log(p1);//Person { name: 'Tom', age: 18, friends: [] }
console.log(p2);//Person { name: 'Jerry', age: 16, friends: [ 'Mary' ] }
console.log(p1.sayName());//Tom
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

King_960725

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值