JavaScript继承方式:原型链与借用构造函数比较

需积分: 5 0 下载量 70 浏览量 更新于2024-08-05 收藏 6KB MD 举报
本文档主要探讨了JavaScript中的两种对象继承方式:原型链继承和借用构造函数继承。这两种方法在实现继承特性时各有优缺点。 ### 原型链继承 **概念**: 在JavaScript中,每个对象都有一个内部[[Prototype]]属性,它指向其构造函数的原型对象。当我们试图访问一个属性或方法时,如果当前对象没有该属性,会沿着原型链向上查找,直到找到或者到达原型链的顶端(`Object.prototype`)。 **优点**: 1. 简单直观,无需显式创建原型对象。 2. 动态绑定,可以通过改变原型链动态添加新属性。 **缺点**: 1. **共享问题**:当原型链中包含引用类型值(如对象)作为原型时,所有通过原型链继承的实例将共享这个引用类型的实例,可能导致数据污染。 2. **参数传递受限**:在创建子类型实例时,无法向父类型构造函数传递参数,除非通过修改实例属性间接实现。 **示例**: ```javascript function Parent() { this.isShow = true; this.info = { name: "yhd", age: 18, }; } Parent.prototype.getInfo = function() { console.log(this.info); console.log(this.isShow); // true } function Child() {} Child.prototype = new Parent(); let child1 = new Child(); child1.info.gender = "男"; child1.getInfo(); // {name: "yhd", age: 18, gender: "男"} let child2 = new Child(); child2.info.gender = "女"; // 修改了共享的info对象 child2.getInfo(); // {name: "yhd", age: 18, gender: "女"} child2.isShow = false; // 修改了自身实例的isShow console.log(child2.isShow); // false ``` ### 借用构造函数继承 **原理**: 通过在子类型构造函数中使用`call`或`apply`方法,将子类型的实例作为`this`上下文调用父类型的构造函数,从而实现继承。 **优点**: 1. 解决了原型链继承中的参数传递问题,可以在子类构造函数中直接调用父类构造函数,并传递参数。 2. 避免了引用属性的共享,每个子实例拥有独立的父类型实例。 **缺点**: 1. **函数方法复用受限**:由于子类不能直接访问父类原型上的方法,所有方法都需要在子类构造函数中重新定义,增加了代码量。 2. **访问限制**:子类实例不能直接访问父类原型上的方法,需要通过`parentName.call(this)`的形式间接调用。 **示例**: ```javascript function Parent() { this.info = { name: "yhd", age: 19, }; } function Child() { Parent.call(this, { gender: "未知" }); // 向父类传递参数 } let child1 = new Child(); child1.info.gender = "男"; console.log(child1.info); // {name: "yhd", age: 19, gender: "男"} let child2 = new Child(); console.log(child2.info); // {name: "yhd", age: 19, gender: "未知"} ``` 总结来说,原型链继承适用于简单的继承场景,而借用构造函数继承则提供了一种更灵活但复杂度更高的方式,特别是在需要传递参数或控制实例化过程时。选择哪种方式取决于具体的应用需求和代码结构。