javascript中实现继承的三种方式(一看就懂)

本文详细介绍了JavaScript中的三种继承方式:原型继承、类继承(通过构造函数实现)以及混合继承,并对比了它们各自的优缺点。

1、原型继承

 	//  父类 
        function Persion(name,age){ 
        	this.name = name; 
        	this.age = age; 
        }
        // 父类的原型对象属性 
        Persion.prototype.id = 10;
        // 子类 
        function Boy(sex){ 
        	this.sex = sex;
        }
        // 继承实现 
        Boy.prototype = new Persion('c5',27);
         var b = new Boy(); 
         alert(b.name)// c5 
         alert(b.id)//10

这种原型继承的特点:既继承了父类的模板,又继承了父类的原型对象。优点是继承了父类的模板,又继承了父类的原型对象,缺点就是父类实例传参,不是子类实例化传参,不符合常规语言的写法。

2、类继承(借用构造函数的方式继承)

        //  父类 
        function Persion(name,age){ 
        	this.name = name; 
        	this.age = age; 
        }
        // 父类的原型对象属性 
        Persion.prototype.id = 10;
        // 子类 
        function Boy(name,age,sex){ 
        	//call apply 实现继承
        	Persion.call(this,name,age);
        	this.sex = sex;
        }
         var b = new Boy('c5',27,'男'); 
         alert(b.name)// c5 
         alert(b.id)//undinfind 父类的原型对象并没有继承


这种原型继承的特点:继承了父类的模板,不继承了父类的原型对象。优点是方便了子类实例传参,缺点就是不继承了父类的原型对象


3、混合继承(原型继承和类继承)

 	//  父类 
        function Persion(name,age){ 
        	this.name = name; 
        	this.age = age; 
        }
        // 父类的原型对象属性 
        Persion.prototype.id = 10;
        // 子类 
        function Boy(name,age,sex){ 
        	//call apply 实现继承
        	Persion.call(this,name,age);
        	this.sex = sex;
        }
        // 原型继承实现  参数为空 代表 父类的实例和父类的原型对象的关系了
	 Boy.prototype = new Persion();
         var b = new Boy('c5',27,'男'); 
         alert(b.name)// c5 
         alert(b.id)//10

这种原型继承的特点:既继承了父类的模板,又继承了父类的原型对象。优点方便了子类实例传参,缺点就是Boy.pertotype = new Persion()  函数又实例一次,函数内部变量又重复实例一次,大程序时候会很好性能。



<think>好的,用户想理解JavaScript原型链继承的核心概念并总结重点知识点。我需要先回顾下相关的引用内容,确保回答准确。 首先,引用[1]提到了原型和构造函数的关系,比如Constructor.__proto__和Constructor.prototype的问题,这可能涉及到原型链的结构。引用[3]讨论了组合继承的优点,结合了原型链和构造函数的特点,这应该是原型链继承个关键点。引用[4]中的例子展示了通过构造函数创建对象,并检查constructor.name和Object.prototype.toString的结果,说明自定义构造函数实例如何通过原型链识别型,但也指出Object.prototype.toString返回的是Object,这可能涉及到原型链的顶端是Object.prototype。 用户之前的问题是关于事件循环,现在转向原型链继承,可能需要从基础开始解释。用户需要核心原理和关键知识点,所以应该分点清晰,结构明确。 首先,原型链继承的原理是每个对象都有个原型对象,通过__proto__链接,直到null。构造函数通过prototype属性指向原型,实例通过__proto__继承属性和方法。需要解释构造函数实例、原型三者的关系,以及原型链如何形成。 关键知识点可能包括: 1. 构造函数、原型对象实例的关系。 2. 原型链的查找机制:属性或方法的查找路径。 3. 组合继承的原理,结合原型链和构造函数继承的优点。 4. instanceof和isPrototypeOf的作用。 5. 原型链继承的缺点,比如引用型共享的问题,以及如何通过组合继承解决。 引用[3]提到组合继承避免了原型链和借用构造函数的缺陷,所以需要说明原型链继承的问题,比如子实例共享父引用属性,而组合继承使用构造函数继承实例属性,原型链继承方法,这样既避免引用共享,又能复用方法。 引用[4]中的例子显示,自定义构造函数实例的constructor.name正确,但Object.prototype.toString返回[object Object],这说明虽然实例的构造函数正确,但对象型识别仍有局限,可能需要其他方法,比如在原型上设置特定标识。 另外,用户可能需要知道如何实现原型链继承,给出代码示例,并解释步骤。例如,将子的prototype指向父实例,从而继承原型的方法,同时通过调用父构造函数初始化实例属性。 还需要提到原型链的终点是Object.prototype,最后是null,这解释了为什么所有对象都有toString等方法。 总结时,要强调原型链继承的核心是通过原型对象的链接实现属性和方法的继承,但需要注意引用型的问题,以及组合继承如何解决这些问题。同时,关键点包括构造函数、原型对象实例的关系,原型链的查找机制,以及组合继承的优点。</think>### JavaScript 原型链继承核心原理与关键知识点 --- #### **、原型链继承的核心原理** 1. **原型链本质** - 每个对象(包括函数)都有个 `[[Prototype]]` 属性(通过 `__proto__` 访问),指向其原型对象。 - **构造函数**通过 `prototype` 属性指向原型对象,**实例**通过 `__proto__` 继承原型对象的属性和方法。 - **链式继承**:若当前对象未找到属性/方法,则沿原型链向上查找,直到 `Object.prototype`(终点为 `null`)[^3]。 2. **原型链继承实现** ```javascript function Parent(name) { this.name = name; this.colors = ['red', 'blue']; } Parent.prototype.sayName = function() { console.log(this.name); }; function Child(name) { Parent.call(this, name); // 借用构造函数继承实例属性 } Child.prototype = new Parent(); // 原型链继承方法 Child.prototype.constructor = Child; // 修正构造函数指向 const child1 = new Child('Tom'); child1.colors.push('green'); const child2 = new Child('Jerry'); console.log(child2.colors); // ["red", "blue"](解决引用型共享问题) ``` --- #### **二、关键知识点总结** 1. **核心三要素** | **角色** | **作用** | **关联关系** | |-----------------|-----------------------------------|----------------------------------| | **构造函数** | 定义实例属性 | `构造函数.prototype` → 原型对象 | | **原型对象** | 存储共享方法 | `实例.__proto__` → 原型对象 | | **实例** | 通过原型链继承属性和方法 | `实例.constructor` → 构造函数 | 2. **原型链继承的问题与解决** - **问题1:引用型共享** 父构造函数中的引用型属性(如数组)会被所有子实例共享[^3]。 **解决**:在子构造函数中通过 `Parent.call(this)` 调用父构造函数,初始化实例属性(组合继承)。 - **问题2:无法传递参数** 直接通过原型链继承时,无法向父构造函数传递参数。 **解决**:组合继承中显式调用父构造函数并传参。 3. **型检测方法** - **`instanceof`**:检测实例是否在对象的原型链上。 ```javascript console.log(child1 instanceof Parent); // true ``` - **`isPrototypeOf()`**:检测某个对象是否在另对象的原型链上。 ```javascript console.log(Parent.prototype.isPrototypeOf(child1)); // true ``` 4. **内置型检测的局限性** ```javascript console.log(Object.prototype.toString.call(child1)); // [object Object] ``` - 自定义对象的 `[[Class]]` 会被统标记为 `Object`,需通过 `constructor.name` 区分具体型[^4]。 --- #### **三、组合继承的优势** 1. **融合两种继承模式** - **借用构造函数**:继承实例属性,避免引用型共享。 - **原型链**:继承原型方法,实现方法复用[^3]。 2. **型检测兼容性** - 支持 `instanceof` 和 `isPrototypeOf()`,准确识别继承关系。 --- #### **四、常见问题解析** 1. **为什么 `Constructor.__proto__ === Constructor.prototype` 是 `false`?** - `Constructor.__proto__` 指向函数的原型(即 `Function.prototype`),而 `Constructor.prototype` 是实例的原型对象,两者不同[^1]。 - **验证**: ```javascript function Foo() {} console.log(Foo.__proto__ === Function.prototype); // true console.log(Foo.__proto__ === Foo.prototype); // false ``` 2. **如何用句话概括原型?** **原型是 JavaScript 实现继承的机制,通过 `__proto__` 形成链式结构,使对象能共享属性和方法**[^1][^3]。 --- ### **相关问题** 1. 如何实现多重继承个子继承多个父)? 2. ES6 的 `class` 语法糖如何优化原型链继承? 3. 如何避免原型链过长导致的性能问题? 4. `Object.create()` 方法在原型链继承中的作用是什么? 5. 如何深拷贝对象以切断原型链关联? --- 通过以上解析,可系统掌握原型链继承的设计思想及实践要点[^3][^4]。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值