JavaScript中的原型继承

想要了解JavaScript中的原型继承,需要先知道原型继承这两个概念。

1.原型

1.1原型关系的检测

isPrototypeOf方法用于测试一个对象是否存在于另一个对象的原型链上。
instanceof运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

		function Fn(){}
		function Fun(){}		
		var f = new Fn()
		
		console.log(f.__proto__ === Fn.prototype);	//t
		
		console.log(Fn.prototype.isPrototypeOf(f))	//t
		
		console.log(Fun.prototype.isPrototypeOf(f))		//f

		console.log(Object.prototype.isPrototypeOf(f))	//t
		
		
		console.log(f instanceof Fn);		//t
		
		console.log( f instanceof Fun );        // f
		
		console.log( f instanceof Object );     // t
1.2原型的应用

当我们给fn的原型身上添加一个方法show,那么在通过new fn()创造出来的实例身上,都可以使用show这个方法。

		function fn(){
			this.haha = "CSDN"
		}
		fn.prototype.show = function(){
			console.log(this.haha)
		}
		var f1 = new fn();
		var f2 = new fn();
		console.log(f1 === f2);		//false
		f1.show();		//CSDN
		f2.show();		//CSDN

以下代码通过原型实现了,任何一个数组都可以使用noRepeat这个自定义的方法实现数组去重。

		Array.prototype.noRepeat = function(){
			var m = []
			for(var i =0;i<this.length;i++){
				if(m.indexOf(this[i])== -1){
					m.push(this[i])
				}
			}
			return m;
		}
		
		var arr = [4,4,3,5,8,6,9,5,5,6,7,0,2]
		var res = arr.noRepeat();
		console.log(res)
		
		var arr1 = ["a","b","c","b","a"]
		var res1 = arr1.noRepeat();
		console.log(res1)

2.继承

所谓继承就是:让一个没有某个属性或方法的对象能够使用另一个具有某个方法或属性的对象的属性或方法。

		var obj = {
			name:"obj",
			show:function(){
				console.log(this.name)
			}
		}
		var obj2 = {
			name:"obj2"
		}
		
		obj.show()		//obj
		obj2.show();	//报错

以上obj2中没有show方法,强行使用则会报错。那么我们如何让obj2也能使用show方法呢?
这时候 我们的原型继承就可以大展身手了。

		function Parent(){
			this.name = "parent"
		}
		Parent.prototype.show = function(){
			console.log("hhh")
		}
		
		function Child(){
			
		}
		//浅拷贝
		Child.prototype = Parent.prototype
		var p = new Parent();
		p.show();		//hhh
		console.log(p.name);	//parent	
		
		var c = new Child();
		c.show();		//hhh
		console.log(c.name);	//undefined

以上通过浅拷贝将Parent原型身上的方法继承了过来,但是如果我们修改了Child原型的show方法,Parent原型身上的方法也会被修改。

		//浅拷贝
		Child.prototype = Parent.prototype
		Child.prototype.show = function(){
			console.log("ggg")
		}
		var p = new Parent();
		p.show();	//ggg
		console.log(p.name);	//parent
		
		var c = new Child();
		c.show();	//ggg
		console.log(c.name);	//undefined

这时候浅拷贝的缺点也就暴露了出来,那么我们使用深拷贝来做。

		//深拷贝
		for(var i in Parent.prototype){
			Child.prototype[i] = Parent.prototype[i];
		}
		Child.prototype.abc = function(){
			console.log("hello")
		}
		Child.prototype.show = function(){
			console.log("ggg")
		}		
		var p = new Parent();
		p.show();		//hhh
		p.abc();		//报错
		console.log(p.name)	//parent
		
		var c = new Child();
		c.show();	//ggg
		c.abc();	//hello
		console.log(c.name)		//undefined

这样做就可以避免浅拷贝带来的负面影响。但是我们可以看到,不论是浅拷贝还是深拷贝都只继承了原型身上的方法,而没有构造函数中的属性。
那么我们继续往下看。

原型继承 — 原型链继承
		function Parent(){
			this.name = "hello world"
		}		
		Parent.prototype.show = function(){
			console.log(this.name)
		}		
		function Child(){
			this.name = "html";
		}		
		Child.prototype = new Parent()
		var p = new Parent()
		p.show();		//hello world

		var c = new Child();
		c.show();		//html

以上如果想在Child的实例c中使用一个属性或方法,那么他的查找流程为:
Child的实例c —> c.__ proto __ —> Child.prototype —> Parent的实例p —> p.__ proto __ —> Parent.prototype
逐级向上查找,找到后就停止查找(就近原则
可以看到在原型链继承中,我们不仅可以继承原型身上的方法和属性,而且还可以继承构造函数中的方法和属性
这个方法其实也又一些缺点,比如 不方便传参

		function Parent(n){
			this.name = n
		}		
		Parent.prototype.show = function(){
			console.log(this.name)
		}		
		function Child(){
		}		
		Child.prototype = new Parent("CSDN")
					
			var p = new Parent("张三")
			p.show();		//张三
			console.log(p.name)		//CSDN
			
			var c = new Child("李四");
			c.show();		//张三
			console.log(c.name);	//CSDN			
总结:
原型链继承的特点:

1.更加的简单,方便,易操作
2.不仅可以继承原型身上的方法和属性,而且还可以继承构造函数中的方法和属性
3.但是,不方便传参

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值