JavaScript中继承的几种方式

1. 原型继承

利用原型(链)让一个对象继承另一个对象的属性和方法

<script type="text/javascript">
	//原型对象的属性和方法,能被实例所访问到
	//每一个构造函数都有一个原型对象
	//每一个原型对象都有一个指针 constructor 指向构造函数
	//每一个实例都有一个内部指针(_proto_)  指向原型对象,
	function Person(name,age){	
	
	}
	Person.prototype.name = "john";
	Person.prototype.age = 20;
	Person.prototype.sayHello = function(){
		console.log(this.name,this.age);
	}
	function Male(){
			
	}
			
	Male.prototype = new Person();//内部__proto__指针 Male.prototype.__proto__ ->(指向) Person.prototype
	var male = new Male();
			
	//这种链式的结构叫做  原型链
	//原型链上的属性和方法能够被实例所访问到
			
	//函数都有prototype, 实例有__proto__
			
	//将其他类型转换成字符串时,默认会调用toString方法,这个方法是顶层原型对象上的方法,可以改写
	//改写之后,转换的结果以改写结果为准
			
	//console.log(male.__proto__ == Male.prototype);//__proto__ 指向父级的 prototype  最终指向Object.prototype,  --证明了JS是基于原型的, JS万物皆对象
		male.sayHello();
</script>

这种继承的缺点是:构造函数原型上的属性在所有该构造函数构造的实例上是共享的,即属性没有私有化,原型上属性的改变会作用到所有的实例上


2. 构造函数基层

A类 B类 B要继承A
让子类具有父类的实例方法
构造函数的继承方式
call和apply继承的方法

<script type="text/javascript">
	function Person(name,age){
		this.name = name;
		this.age = age;
		this.sayHello = function(){
			onsole.log(this.name,this.age);
			}
	}
	function Male(name,age){
		Person.call(this,name,age);//call参数列表
	}
			
	//apply
	function Female(name,age){
		Person.apply(this,[name,age]);//apply参数数组
	}
	var text1 = new Male("text1",20);
	text1.sayHello();
			
	var text2 = new Female("text2",21);
	text2.sayHello();
	
</script>

这种方法继承的缺点是:实现了属性的私有化,但是子类无法访问父类原型上的属性。


3. 组合继承

使用原型链实现对原型属性和方法的继承
通过伪造(冒充)构造函数来实现对实例属性的继承

<script type="text/javascript">
	function Person(name,age){
		this.name = name;
		this.age = age;
	}
	Person.prototype.sayHello = function(){
		console.log(this.name,this.age);
	};
	function Male(name,age){
		Person.call(this,name,age);
	}
			
	//Male.prototype = new Person();//这种方法会反复调用Person
	//Male.prototype = Person.prototype;//这种方法会扰乱父子类之间的关系,会出现地址拷贝
	//子类添加给自己的一些方法,父类不应该访问到
			
	//遍历Person.prototype
	for(var i in Person.prototype){
		Male.prototype[i] = Person.prototype[i];
	}
			
	var male = new Male("john",20);
	male.sayHello();
	
</script>

4. 寄生式继承

在原型式继承得到对象的基础上,在内部再以某种方式来增强对象,然后返回。

<script type="text/javascript">
	function Person(name,age){
		this.name = name;
		this.age = age;
	}
	Person.prototype.sayHello = function(){
		console.log(this.name,this.age);
	};
	function Male(name,age){
		Person.call(this,name,age);
	}
			
	//借用Object.create方法
	Object.create();
	var obj1 = {a:1};
	var obj2 = {b:2};
	var a = Object.create(obj1);
	console.log(a); 
	
	Male.prototype = Object.create(Person.prototype);
	//需要纠正指向问题
	Male.prototype.constructor = Male;
	
	var male = new Male("john",20);
	male.sayHello();
			
</script

5. ES6继承

ES6中有关class的继承方式,引入了extends关键字。但其本质仍然是构造函数+原型链的组合式继承。

<script type="text/javascript">
	class Person{
		constructor(name,age){
			this.name = name;
			this.age = age;
		}
		sayHello(){
			console.log(this.name);
		}
		static foo(){ //它是静态方法,就是这个类本身的方法 , 如果想要访问foo  需要通过类本身调用 Person.foo()
			console.log("foo");
		}
	}
	class Male extends Person{
		constructor(name,age){
			super(name,age); //在构造函数里面它是指向父类的构造函数
			this.sexy = "male";
		}
		sayHi(){
			super.sayHello();//指向父类的原型对象
		}
				
		static bar(){
			super.foo();//指向父类
		}
	}
			
	console.log(Person.prototype)
	console.dir(Person)
	Person.foo()
	var male = new Male("john",20)
	male.sayHello();
	male.sayHi();
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值