JavaScript 是基于原型的语言,Prototype 和 Prototype Chain 是实现继承的一种机制。每个 JavaScript 对象在创建时均关联原型对象,它们均有一个内置属性,通过 ES5 __proto__
或 ES6 Object.getPrototypeOf
获得。原型链是对象通过其原型与其他对象相关联的链,当你访问一个对象的属性或方法时,若在对象本身没有找到,则继续在该对象的原型上查找,若原型上也没有,则继续在原型的原型上查找,直到找到该属性或方法或到达原型链的末端,原型链的末端是 Object.prototype
,若在原型链的任何地方找不到指定的属性或方法,则返回 undefined
。
什么是原型和原型链
在 JavaScript 中,每个对象都有一个原型对象,原型对象也是一个普通的对象,它有一个 constructor 属性指向创建它的构造函数,它也有一个原型对象,这样就构成了一个原型链。在 JS
中,面向对象的实现是基于原型的,而不是基于类的。就算 ES6 中引入了 class
关键字,但是它只是语法糖,本质上还是基于原型的。
题目: https://juejin.cn/post/6959043611161952269#heading-59
js
//这是一个构造函数
function Animals(name){
this.name=name;
}
//在构造函数的原型上添加属性和方法
Animals.prototype.sleep=function(){
console.log(`${this.name} is sleeping`);
}
//创建对象
const dog=new Animals(Bob);
//定义子类构造函数
function Cat(name,age){
Animals.call(this.name);
this.age=age;
}
//设置子类的原型为父类的实例,实现继承
Cat.prototype=Object.create(Animals.prototype);
Cat.prototype.constructor=Cat;
//在子类上面添加方法
Cat.prototype.miao=function(){
console.log(`${this.name}miaomiao`)
//创建子类实例
const huahua=new Cat(`huahua`,1);
const kitty=new Cat(`kitty`,2);
//调用继承的方法和子类自己的方法
huahua.miao();
kitty.sleep();
}
- 优势:
- 实现简单,只需要修改原型对象就行
- 能实现基于原型的方法共享,提高内存利用率
- 符合js面向对象风格易于理解
- 不足:
- 继承层次过多时,性能受到影响
- 原型链继承导致对象之间引用关系复杂,不利于调试
应用场景
- 组件库开发,开发按钮组件库
js
function Button(label) {
this.label = label;
}
Button.prototype.click = function() {
console.log(`${this.label} button clicked`);
};
function IconButton(label, icon) {
Button.call(this, label);
this.icon = icon;
}
IconButton.prototype = Object.create(Button.prototype);
IconButton.prototype.constructor = IconButton;
IconButton.prototype.click = function() {
console.log(`${this.icon} icon button clicked`);
};
const myButton = new Button('Submit');
myButton.click(); // Submit button clicked
const myIconButton = new IconButton('Upload', '📁');
myIconButton.click(); // 📁 icon button clicked