【前端基础】JavaScript继承

学习js的几种继承方式

文章旨在梳理JavaScript中几种继承方式

一、原型链继承

//父类
var Person = function(name,age){
	this.name = name;
	this.age = age;
}
//在父类上添加方法,子类可以继承该方法
Person.prototype.getName = function(){
	console.log(this.name);
}

Person.prototype.getSex = function(){
	console.log(this.sex);
}
//子类
var Child = function(name,sex){
	this.name = name;
	this.sex = sex;
}
// 报错:子类不可直接在prototype上添加属性和方法,因为会影响父类的原型
// Child.prototype.getSex = function(){
// 	console.log(this.sex);
// }

//继承,让Child继承Person的方法
Child.prototype = new Person();
//将Child实例的Constructor指向自己的构造函数Child
Child.prototype.constructor = Child;
//因为此模式会共享属性和方法,所以当一个实例修改属性和方法时会影响其他实例,而且子类型无法向超类型传递参数(可以通过call传递,得出改进方法组合继承)。
var person1 = new Child('Alice');
console.log(person1.constructor);//[Function: Child]
person1.getName();//继承了Person的方法
person1.age = 18;//继承了Person的属性
console.log(person1);//Child { name: 'Alice', sex: 'female', age: 18 },继承了Person的属性并且保留自己的属性
  • 缺点:

(1)修改一个实例可能会影响其他实例,因为当你修改一个实例的属性和方法时,可能是直接在原型上修改的,因此其他继承次原型的实例也可能被修改:

//当一个实例修改属性和方法时会影响其他实例
function person () {}
person.prototype = {
   constructor: Person,
   name: 'xu',
   age: ['1', '2'],
   sex: '男',
   showAge: function () {
      console.log(this.age);
   }
}

var person1 = new person();
var person2 = new person();
person1.age.push('3');
//是对属性的引用,那么你对它操作的时候,实际上就是对原型上操作。但是
console.log(person1.age, person2.age); // ['1', '2', '3'] , ['1', '2', '3']
person1.age = ['1'];
//这就不同了,相当于给person1这个对象实例添加了一个属性,不是给原型添加。关键在于等于。
console.log(person1.age, person2.age); // ['1'] , ['1', '2', '3']

扩展:
Vue中的组件的data 为什么是一个函数?
https://blog.csdn.net/weixin_42554191/article/details/109702420
防止修改实例时影响其他实例。

(2)子类无法向父类传递参数(改进方法:和call一起组合继承)

二、修改this的指向来继承(call,apply,bind)

//利用call继承(相关知识点:函数参数传递)
function Animal(name,age){
	this.name = name;
	this.age = age;
	console.log(arguments);//arguments是子类向父类传递的参数
	this.arg = Array.prototype.slice.call(arguments,0);
	this.getName = () =>{
		console.log(this.name);
	}
	this.getOtherInfo = (key) =>{
		if(this.name === key){
			console.log(this.age);
		}
        if(this.age === key){
        	console.log(this.name);
        }
	}
}

function bird(){
	var arg = Array.prototype.slice.call(arguments,0);
	console.log(arg);
	Animal.call(this,arg);//可以通过这个向父类传递参数
}

var b1 = new bird(1,2,3);
b1.age = 18;//继承了父类的属性
b1.name = 'AA'//继承了父类的属性
console.log(b1);
// 输出:
// bird {
//   name: 'AA',
//   age: 18,
//   arg: [ [ 1, 2, 3 ] ],
//   getName: [Function (anonymous)],
//   getOtherInfo: [Function (anonymous)]
// }
b1.getName();//AA,继承了父类的方法
b1.getOtherInfo('AA')//18
  • 缺点:

函数无法复用(为什么无法复用,有知道的大神可以在评论区告诉我一下吗?)

三、组合继承

结合一、二两种继承(推荐)

function parent(name) {
    this.name = name
}
 
parent.prototype.sayName = () => {
    alert(this.name)
}
 
function child(name, age) {
    parent.call(this, name)//通过此可以将子类参数传递给父类
    this.age = age
} 
 
child.prototype = new parent()
child.prototype.constructor = child
child.prototype.sayAge = () => {
    alert(this.age)
}

参考:

Vue中的组件的data 为什么是一个函数?
https://blog.csdn.net/weixin_42554191/article/details/109702420

原型链实现继承的6种方式:
https://blog.csdn.net/weixin_33750452/article/details/91453468?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-4&spm=1001.2101.3001.4242

什么是原型、原型链、继承?
https://blog.csdn.net/xiao___fang/article/details/90450711

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值