JavaScript继承
2021/9/23 17:13:44
本文主要是介绍JavaScript继承,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
继承
在ECMAScript中实现继承的方式主要是通过原型链实现的。
1.原型链继承
通过原型链继承的基本思想是:通过原型,继承引用类型的属性和方法。
注意:所有的引用类型都继承自Object。
两个函数:Animal、Dog
一个Dog实例:dog
通过原型链继承,实现让dog调用sayName()方法
function Animal(name) { this.name = name; } Animal.prototype.sayName = function () { console.log('my name is ', this.name); } function Dog(name, color, age) { this.name = name; this.color = color; this.age = age } // 原型链继承 Dog.prototype = new Animal(); //修改Dog原型中的constructor指针指向 Dog.prototype.constructor = Dog; Dog.prototype.sayColor = function () { console.log('my color is ', this.color); } let dog = new Dog('小白', '白色', 2) dog.sayColor(); //白色 dog.sayName(); //小白 成功调用该方法 console.log(Dog.prototype.constructor); //[Function: Dog]
当Dog的原型成为Animal的实例时,就实现了原型链的继承。但是Dog里面的constructor指针就会销毁,那么当我们查找dog实例的构造函数时就会向上找到Animal原型的constructor指针,这时,dog的构造函数就为Animal。
但是,dog的构造函数明明是Dog,通过原型链继承,改变这个指向,所以,我们要手动的修改回来,让他指向回Dog。
此时,我们就能调用Animal中的sayName()方法。
1.1 注意
- 若我们需要在子类的原型中添加方法,需要在改变子类的constructor指向之后再添加,否则调用不了该方法。
例如:我们在Dog的原型中添加了一个sayColor()方法,需要在Dog原型的constructor指向改变之后再添加。
- 若我们用字面量形式为子类的原型中添加多个方法,那么这就会破坏掉原来的原型链,这样子类的constructor就会指向Object。
Dog.prototype = { getDogName() { console.log(this.name); }, someOtherMethod() { return false; } }; console.log(Dog.prototype.constructor); //[Function: Object]
1.2 判断类型
我们都知道,通过instanceof操作符可以判断一个实例是否属于某个构造函数,即该实例的原型链中是否出现某个构造函数。
isPrototypeOf()
通过isPrototype()这个方法,我们可以判断某个构造函数的原型链中是否包含某个实例,是则返回true,不是则返回false。
//true console.log(Object.prototype.isPrototypeOf(dog)); //true console.log(Animal.prototype.isPrototypeOf(dog)); //true console.log(Dog.prototype.isPrototypeOf(dog));
1.3 原型链的问题
- 当原型中包含引用值时,原型中的引用值会在所有实例中共享,而当引用值被修改时,修改后的值就会被所有实例共享。
- 子构造函数在实例化时不能给父构造函数传参。
2.经典继承
经典继承又称盗用构造函数,用于解决原型包含引用值导致的继承问题。
用法:在子构造函数中使用call()或apply()方法,改变this指向,指向当前子构造函数并调用父构造函数。这样之后每个实例都会拥有自己的引用值类型数据,就不会共享而导致出现问题。
// 父'类' function Animal() { this.name = 'aaa' this.categorys = ['cat', 'dog'] } // 子'类' function Dog() { // 改变this指向 继承属性 Animal.call(this); }
2.1 经典继承优点
- 可在子构造函数中向父构造函数传参
- 可给子构造函数的实例添加新的属性
2.2 经典继承的问题
- 必须在构造函数中定义方法,导致函数不能重用
- 子构造函数不能访问父构造函数原型上定义的方法
- 每个子构造函数都拥有父构造函数的副本,浪费内存,影响性能
注意:不能使用instanceof操作符和isPrototypeOf()方法判断继承的父构造函数,因为只继承了父构造函数的实例方法、属性,没有继承父构造函数原型对象中的属性、方法。
3.组合继承
又称伪经典继承,结合了原型链继承和经典继承的优点,是JS使用最多得继承模式。
用法:通过原型链继承原型上的属性和方法;通过经典继承继承实例属性。
优点:将方法定义在原型上,实现重用;还可以让每个实例都拥有自己的实例
function Animal() { this.name = 'aaa' this.categorys = ['cat', 'dog'] } Animal.prototype.sayName = function () { console.log(this.name); } // 子'类' function Dog() { // 改变this指向 继承属性 Animal.call(this); } // 继承方法 Dog.prototype = new Animal() var d1 = new Dog(); d1.categorys.push('rabbit') var d2 = new Dog(); console.log(d1.categorys); //[ 'cat', 'dog', 'rabbit' ] console.log(d2.categorys); //[ 'cat', 'dog'] d1.sayName() //aaa
这篇关于JavaScript继承的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-07-02springboot项目无法注册到nacos-icode9专业技术文章分享
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现
- 2024-06-03为什么以及如何要进行架构设计权衡?
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)