面向对象精要——构造函数和原型对象( Prototype )

本文主要介绍了JavaScript中构造函数和原型对象的相关知识。构造函数用new创建对象时调用,可让同一构造函数创建的对象有相同属性和方法。原型对象可看作对象基类,几乎所有函数都有prototype属性,对象实例通过[[Prototype]]跟踪原型对象,对原型对象的改变会反映到所有实例上。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、构造函数

构造函数就是用 new 创建对象时调用的函数。使用构造函数的好处在于所有用同一个构造函数创建的对象都有同样的属性和方法。

function Person(name) {
	this.name = name;
	this.sayName = function() {
		console.log(this.name);
	}
};	//构造函数首字母大写
//创建对象
var person1 = new Person();
var person2 = new person;		//如果不用传参数,可以忽略小括号

console.log(person1 instanceof Person);	// true

当调用构造函数时,new 会自动创建 this 对象,且其类型就是构造函数的类型。
始终确保用 new 调用构造函数,否则,构造函数只不过是个没有返回语句的普通函数:

var person1 = Person("Tom");
console.log(person1 instanceof Person);	// false
console.log(typeof person1);	//	"undefined"
console.log(name);		//	"Tom"

这里的 Person 不是被 new 调用,构造函数中的 this 对象等于全局 this 对象,且由于 Person 构造函数依靠 new 提供返回值,所以这里的 person1 变量为 undefined。
在严格模式下,不通过 new 调用 Person 构造函数会报错,因为在严格模式下并没有为全局对象设置 this,全局对象的 this 为 undefined。

二、原型对象——prototype

可以把原型看成对象的基类。
几乎所有的函数(除了一些内建函数)都有一个名为 prototype 的属性,该属性是原型对象用来创建新的实例。所有创建的对象实例共享该原型对象,且这些对象实例可以访问原型对象的属性。
1. [[Prototype]] 属性
一个对象实例通过内部属性 [[Prototype]] 跟踪其原型对象。该属性是一个指向该实例使用的原型对象的指针。
在这里插入图片描述
可以调用对象的 Object.getPrototypeOf() 方法读取 [[Prototype]] 属性的值。
也可用 isPrototypeOf() 方法检查某个对象是否是另一个对象的原型对象。
无法给一个对象的原型属性赋值。

2. 在构造函数中使用原型对象
原型对象的共享机制使得它们成为一次性为所有对象定义方法的理想手段。将方法放在原型对象上并用 this 访问当前实例是更有效的做法。

function Person(name) {
	this.name = name;
}
Person.prototype.sayName = function() {
	console.log(this.name);
}

也可以在原型对象上存储其他类型的数据,但在存储引用值时需注意,这些引用值会被多个实例共享!

也可以使用字面量形式替换原型对象:

function Person(name) {
	this.name = name;
}
Person.prototype = {
	sayName: function() {
		console.log(this.name);
	},
	toString: function() {	//do something	}
}

这种定义方法不需要多次键入 prototype ,非常方便,但是有一个副作用,就是使用字面量形式改写原型对象改变了构造函数的属性,因此它现在指向 Object 而不是 Person。因为原型对象有一个 constructor 属性,这是其他对象实例所没有的。
当一个函数被创建时,它的 prototype 属性也被创建,且该原型对象 prototype 的 constructor 属性指向该函数。
在这里插入图片描述
上面的代码为了避免上述问题,需要在改写原型对象时手动重置其 constructor 属性:

function Person(name) {
	this.name = name;
}
Person.prototype = {
	constructor: Perosn,
	
	sayName: function() {
		console.log(this.name);
	},
	toString: function() {	//do something	}
}

3. 改变原型对象
因为 [[Prototype]] 属性只是包含一个指向原型对象的指针,所以任何对原型对象的改变都立即反映到所有引用它的对象实例上。这意味着给原型对象添加的新成员都可以立即被所有已存在的实例使用。
当在一个对象上使用 Object.seal() 或者 Object.freeze() 时,完全是在操作对象的自有属性,无法添加封印对象的自有属性或者改变冻结对象的自有属性,但是仍然可以通过在原型对象上添加属性来拓展这些实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值