原型式继承是借助原型基于已有的对象创建新对象,同时还不必因此创建自定义类型。
🌰 示例:
function Person(friendship) {function Creator() {}Creator.prototype = friendship;return new Creator();}
在函数内部,先创建 临时性的构造函数,然后将传入的对象作为这个 构造函数的原型,最后返回这个临时构造函数的一个实例。从本质上,该函数对传入的对象执行了一次 浅拷贝。
// 作为另一个对象的基础const friendship = {name: 'unamed',friends: ['Amy', 'Ben', 'Tom'],};// 返回新实例对象,该实例对象原型为 Personlet uzi = Person(friendship);uzi.name = 'Uzi';uzi.friends.push('Peter');let kat = Person(friendship);kat.name = 'Kat';kat.friends.push('Sid');// 原型中的基本类型属性和引用类型属性被两个实例对象共享console.log(uzi.friends);// ["Amy", "Ben", "Tom", "Peter", "Sid"]
原型式继承需要有一个对象可以作为另一个对象的基础。如果有这么一个对象的话,可以把它传递给实例生成函数,然后再根据具体需求对得到的对象加以修改即可。
ECMAScript 5 通过新增 Object.create()
方法规范化了原型式继承。这个方法接收两个参数:一个用作新对象原型的对象和一个为新对象定义额外属性的对象(可选)。
实际上就是将 Person 构造函数替换成Object.create
const friendship = {name: 'unamed',friends: ['Amy', 'Ben', 'Tom'],};let uzi = Object.create(friendship);uzi.name = 'Uzi';uzi.friends.push('Peter');let kat = Object.create(friendship);kat.name = 'Kat';kat.friends.push('Sid');console.log(uzi.__proto__.friends);// ["Amy", "Ben", "Tom", "Peter", "Sid"]console.log(kat.__proto__.friends);// ["Amy", "Ben", "Tom", "Peter", "Sid"]
引用类型值的属性始终都会共享相应的值,多个实例对象对引用类型的操作会被篡改。