JavaScript | 原型链 & 继承

整个原型链大体可以用下图来表示

 

当我们写下 let fn = new Fn()的时候,会发生什么呢?

1. let fn = {}

2. fn.__proto__ = Fn.prototype

3. Fn.call(this) //调用Fn的构造函数并指向fn对象

使用原型链来实现继承有两种写法

1:A.prototype.__proto  = Fn.prototype。

每一个原型对象中都有一个指针.__proto__,指向的是父类的prototype对象,即默认是指向Object.prototype, 如果想让A继承Fn,只需改变该指针的指向即可:A.prototype.__proto  = Fn.prototype。

这种方法

1.保留A自身的原型变量(方法)

2.可以继承Fn的原型方法

3.不能继承Fn中的实例变量(方法)。

function Fn(){
	 this.name = 'i am Fn';
	}
	function A(){ }

	Fn.prototype.prototype_Fn = 'i am prototype_Fn'	
	A.prototype.prototype_A = 'i am prototype_A'


   //1 原型链第一种.保留B自身的原型变量(方法),可以继承A的原型方法 ,不能继承A中的实例变量(方法)。
	A.prototype.__proto__ = Fn.prototype;

	let a = new A();
	console.log(a)
	console.log(a.prototype_A); //  i am prototype_A 保留A的原型变量
	console.log(a.prototype_Fn); //i am prototype_Fn 继承Fn的原型变量
	console.log(a.name); //undefine 无法继承Fn的实例变量
        console.log(A.prototype.constructor) //还是A的构造函数

顺带一提,es6 class中的继承好像就是这种方式。

2:A.prototype = new Fn()

这种方法,相当于创建了一个Fn实例对象,然后覆盖A的原型对象;

1.不能保留A自身的原型变量(方法)

2.可以继承Fn的原型方法

3.继承Fn中的实例变量(方法)。

	function Fn(){
		this.name = 'i am Fn';
	}
	function A(){ }

	Fn.prototype.prototype_Fn = 'i am prototype_Fn'	
	A.prototype.prototype_A = 'i am prototype_A'


	A.prototype = new Fn();
	let a = new A(); //相当于创建了一个Fn对象,然后赋值给a
	console.log(a)
	console.log(a.prototype_A); //  undefine 不能保留A自身的原型变量
	console.log(a.prototype_Fn); //i am prototype_Fn 继承Fn的原型变量
	console.log(a.name); //i am Fn 可以继承Fn的实例变量,因为就是把一个Fn实例覆盖掉A的原型对象
        console.log(A.prototype.constructor) // 变成了Fn的构造函数

 

3:使用call/apply借用父类的构造函数

function ChinaPerson(name){
		this.china_walk = 'i am ' + name+ ' can walk in china way';
	}
	function UkPerson(name){
		this.uk_walk = 'i am ' + name+ ' can walk in uk way';
	}
	ChinaPerson.prototype.proto_Walk = 'prototype walk china'

	function Man(){
		// 这里的this就是实例man
		// ChinaPersib.call意思是调用父类的构造函数,并传入该实例进行构造
		// 可以调用多个call多继承
		ChinaPerson.call(this,'刘嘉鹏'); 
		UkPerson.call(this,'liuj4');
	}
	Man.prototype.proto_man = 'proto_man';


	let man = new Man();
	console.log(man.china_walk); //i can walk in china way 继承父类的实例变量
	console.log(man.uk_walk); // i can walk in UK way //继承父类的实例变量
	console.log(man.proto_Walk) //undefined 获取不到父类的原型成员
	console.log(man.proto_man) //proto_man  保留自身的原型成员

	// Man.prototype.__proto__ = ChinaPerson.prototype //加上这句即可继承父类的原型成员

 

总结一下:

1.A.prototype.__proto__ = Fn.prototype: 原型链继承,无法继承父类的实例成员;

2.A.prototype = new Fn(): 用父类实例对象来覆盖A的原型对象,会丢失A本身的原型成员;

3.使用call来调用父类的构造函数实现继承,无法继承父类的原型成员;

4. 使用1+3 / 2+3组合,但只要使用了A.prototype = new Fn(),就必定会丢失A本身的原型成员;

 

以上纯属个人学习经验,若有错误,还望指出~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值