}
var p=new Person()对应的原型链结构为
每个构造函数都有一个prototype属性prototype
每个对象都有一个__proto__ 属性,它指向创建该对象的构造函数的原型。事实上,这个属性指向[[prototype]],但是[[prototype]]是一个内部属性,我们无法访问它,所以我们使用_proto_来访问它。
对象可以使用__proto__ 来查找不属于该对象的属性。 __proto__ 将对象连接起来形成原型链。
默认原型链是:
当前对象--constructor.prototype--Object.prototype--null
请注意, 原型和指向该构造函数的实例上都有一个构造函数构造函数。
Function.prototype.constructor===new Function().constructor
三.构造函数继承
结构继承
原型继承
实例继承(闭包继承)
复制继承
组合继承
寄生组合遗传
需要考虑的优缺点:实例化次数,是父类还是子类的实例,是否可以重用
1.构造继承
使用父类的构造函数增强子类的实例相当于将父类的实例属性赋值给子类。
函数动物(){
this.species="动物";
}
函数猫(名称){
动物.call(这个)
动物.应用(这个)
//相当于Animal()
//this.species="Animal" this 指向Cat 的内部
console.log(this)//猫
this.name=名称;
}
var cat=new Cat("大毛") 缺点:
1、实例不是父类的实例,而是子类的实例。
2、只能继承父类的实例属性和方法,不能继承原型属性和方法。
2.原型继承
使用构造函数的原型指向父对象的实例时,需要注意将子构造函数的构造函数重定向到自己。因为使用prototype指向父构造函数的原型,会导致原型链混乱。
Cat.prototype=new Animal();
Cat.prototype.constructor=Cat;
var cat1=new Cat("大毛","黄色");
警报(cat1.species); //动物原型继承升级版function Animal(){ }
Animal.prototype.species="动物";
Cat.prototype=Animal.prototype;
Cat.prototype.constructor=Cat;
var cat1=new Cat("大毛");
警报(cat1.species); //动物的缺点:
1.无法实现多重继承
2、创建子类实例时,不能向父类构造函数传递参数。
3.实例继承
向父类实例添加新功能并将其作为子类实例返回
函数猫(名称){
var 实例=new Animal();
实例.名称=名称|| "";
返回实例;
}
var cat1=new Cat("大毛") 缺点
1、实例是父类的实例,不是子类的实例
2.不支持多重继承
4.拷贝继承
将父对象的所有属性和方法复制到子对象中
函数动物(){}
Animal.prototype.species="动物";
函数猫(名称){
这个.name=名称;
}
函数扩展(子级,父级){
var p=Parent.prototype;
var c=Child.prototype;
for (var i in p) {
c[i]=p[i];
}
}
extebd(猫,动物)
var cat1=new Cat("大毛")
警报(cat1.species)缺点:
1.效率低,内存占用高(因为需要复制父类的属性)
2. 无法复制对象和数组
5.组合继承通过调用父类构造函数,继承父类的属性并保留可以传递的参数,然后使用父类实例作为子类原型,实现函数复用
函数Animal(){ this.species="动物"}
函数猫(名称){
动物.应用(这个)
这个.name=名称
}
Cat.prototype=new Animal()
Cat.prototype.constructor=Cat
var cat1=new Cat("大毛") 优点:
1. 可以继承实例属性和方法,也可以继承原型方法。
2.它是子类的实例,也是父类的实例。
3.可传递参数
4. 函数可以复用
缺点:调用了两次父类构造函数,生成了两个实例。
寄生组合继承通过计划生育去掉父类的实例属性,这样当父类的构造函数被调用两次时,实例就不会被初始化两次。
函数猫(名称){
动物.call(这个)
这个.name=名称
}
(功能(){
//创建一个没有实例方法的类
var Supe=函数(){}
超级.prototype=动物.prototype
//使用实例作为子类的原型
Cat.prototype=new Super()
Cat.prototype.constructor=Cat
}())
var cat=new Cat("大毛") 优点
1、与组合继承相比,减少了一次实例化父类的需要,节省内存。
四、非构造函数的继承
object() 继承
浅拷贝
深拷贝
1.objecc()继承实现object()函数,将子对象的prototype属性指向父对象,从而将父子对象连接在一起。
函数对象(o){
函数F(){}
F.原型=o
返回新的F()
}
var guangzhou=object(Chinese)2.浅拷贝将父对象的所有属性复制到子对象中,也可以实现继承
函数复制(p){
var c={}
for(var i in p){//[]遍历牵引力值{}然后遍历属性名
c[i]=p[i]
}
返回c
}3.深拷贝深拷贝,可以实现数组和对象的真实拷贝,只需要递归调用浅拷贝
函数深度复制(p,c){
var c=c || {}
for(var i in p){
if(typeof i==="object"){ //typeof arr typeof object=object
var c[i]=(p[i].constructor===数组) ? []: {}
深度复制(p[i], c[i])
}别的{
c[i]=p[i]
}
}
【深入理解JavaScript:原型、原型链与继承机制】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
终于看懂了什么是原型和原型链!
有6位网友表示赞同!
以前总是对继承的概念感到困惑,现在明白了两种不同的方式。
有10位网友表示赞同!
这个知识点太重要了,以后写代码肯定要用到。
有18位网友表示赞同!
感觉学习这些概念还是比较抽象的,需要多加练习巩固
有16位网友表示赞同!
原来构造函数和非构造函数都可以实现继承啊,挺开眼的!
有9位网友表示赞同!
这个标题涵盖了javascript的基础知识,入门必备!
有17位网友表示赞同!
看完这篇文章感觉对javascript的理解又提升了一层。
有11位网友表示赞同!
分享学习心得:在理解原型链时,可以先从简单的例子入手,循序渐进。
有11位网友表示赞同!
代码实现和解释都写的很详细很清晰,很容易理解!
有12位网友表示赞同!
计划把这次学到的知识应用到实际项目中试试手。
有19位网友表示赞同!
希望以后能继续学习深入的继承机制!
有15位网友表示赞同!
这个标题涵盖了好多概念,让我对javascript的基础更扎实了。
有14位网友表示赞同!
这种类型的文章很实用,可以直接用于解决编程问题!
有6位网友表示赞同!
建议补充一些关于原型链的常见面试题和技巧。
有10位网友表示赞同!
感谢作者分享这么好的学习资源!
有20位网友表示赞同!
这篇文章给我对javascript的理解带来了很大的帮助!
有18位网友表示赞同!