木灵鱼儿
阅读:2364
JavaScript里面继承是怎样实现的?如何避免原型链上的对象被共享?
JavaScript里面继承是怎样实现的?
最简单的就是通过原型链继承,然后衍生出几种方法:构造函数继承、组合继承、原型式继承、寄生继承、寄生组合式继承。
function Box() {
this.name = "鱼儿",
this.age = 666
}
Box.prototype.run = function(){
return this.name;
}
function Pox() {
this.run = function() {
alert(this.name + this.age);
}
}
Pox.prototype = new Box();
var pox1 = new Pox();
通过Pox的prototype继承Box构造函数,那么这里Pox.prototype = new Box();发生了什么呢?
首先new Box()会创建一个新的对象,然后将Box的this指向这个对象,这个对象因此会获取到Box构造函数的方法和原型,然后返回出这个对象。
此时Pox.prototype =这里就发生了“赋值”操作,Pox原有的原型被覆盖成new Box()返回的新对象,Pox原型如果之前有方法就会消失。
这里其实可以再理解为,Pox的prototype等于Box的prototype;因为原型的特殊,这里的等于并不是实际的等于,他是相当于将Pox的prototype指向Box的prototype,而其原有的内容则删除了。
又因为原型的constructor的指针指向构造函数本身,因此,Pox也可以获取到Box的独立属性this.name和this.age,那么,这个就是所谓的原型链上的对象共享了。
如何避免原型链上的对象被共享?
通过call方法,将Box的独立属性复制一份到Pox上,这样Pox就可以在创建的独立环境中拥有Box的独立属性,而且不与其他子类共享。
function Box() {
this.name = '鱼儿',
this.age = 666
}
Box.prototype.run = function(){
return this.name;
}
function Pox() {
Box.call(this)
this.run = function() {
alert(this.name + this.age);
}
}
Pox.prototype = new Box();
var pox1 = new Pox();
var pox2 = new Pox();
这样pox1和pox2 的this.name和this.age其实是相互独立的,而且和Box也是独立的,他们三个任何一个独立属性改变都不会相互有影响。
但是后面的Pox.prototype = new Box();实际上还是获取到了Box的独立属性,因为原型的constructor指针的关系,但是原型链之间的获取是有顺序的,也就是优先在Pox的独立属性中查找-----然后到Pox的原型查找---然后再到Box的独立属性,但是因为我们call了一份相同的内容下Pox独立属性里面,所以每次获取值都是获取到Pox下的,这就可以达到不共享了。
然后更加完美点的就是寄生组合式继承,多了一个中转函数和寄生函数,具体我自己也还不是特别懂,后期再讲吧!
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。
相关推荐
屏蔽属性
前言对于js的原型链继承,大部分都是知道的,但是对于以下内容,很多人可能并不清楚或者理解不完整,那就是屏蔽属性。什么是屏蔽属性,其实这个功能来源于面向对象语言中的多态,表示父级定义的属性,在子级可以自己扩展,虽然属性名相同,但是功能却可以不同。由于js的继承,它不像强类型语言是完全的复制,js对于继承是通过原型链的方式,当子级没有的情况下会通过在原型链上查找。那么子级如果需要覆写某一个属性,显然它是绝对不能直接修改原型链上的内容,这回导致所有继承的子类产生问题,这显然是不合适的。于是就有了屏蔽属性,当子级去覆写一个原型上存在的属性时,其实并不会去修改原型链的属性,而是给子级自己添加一个对...
第五章 代码复用模式
代码复用是一个既重要又有趣的话题。如果你面对自己或者别人已经写好的代码,而这些代码又是经过测试的、可维护的、可扩展的、有文档的,这时候你只想写尽量少且可以被复用的代码就是一个再自然不过的想法。当我们说代码复用的时候,第一件想到方式就是继承,为此你可能看到JavaScript很多方式用于实现“继承”。什么是类?如果有一个过程,这个过程能产生一个实例,实例是对象,那这个过程就是类。JavaScript是基于原型面向对象程序设计的,那么它的继承方式也是基于原型实现的,而JavaScript是没有类的,只有构造函数,且支持new用法,所以看上去就和类的用法相似,但是本质还是一个函数,而继承也是一...
第二章 字面量与构造函数
前言JavaScript中可以使用字面量的形式去声明对象,相比较使用构造函数去声明,更加准确且不容易出错,代码也更加简洁,这里讨论常见的类型中,为什么基于字面量的形式更加可取。对象字面量当我们考虑创建一个键-值对哈希表时(在其他语言被称为关联数组),我们可以从一个“空”对象开始,然后再根据需要向其添加所需要的内容,对于按需对象创建方式而言,对象字面量表示法是一种非常理想的选择方法。var dog = {}; dog.name = "jingmao"; dog.getName = function() { return dog.name; } //删除和复写也...
对象与原型的继承组合模式中仿冒和继承不会冲突吗?
代码部分:function Box(name) { this.name = name; this.famil = ['爷爷','奶奶','爸爸','妈妈']; }; Box.prototype.run = function() { return this.name + this.famil; }; function Desk(name) { Box.call(this,name); }; Desk.prototype = new Box(); 通过对象仿冒,将Box的属性仿冒到Desk中,这样就可以传入参数,也可以算是继承了,但是后面我们又通过Des...
关于面向对象判断是否原型属性的疑问
首先我们需要创建一个构建函数,并为它添加一个实例属性(实例就是被运行的函数)。function Box() {}; var box1 = new Box(); box1.name = 'mu'; 每个函数都会有一个原型,原型里的数据是共享的,多个变量box1运行同一个函数Box(),这个Box()函数原型中的数据是共有的,并且引用地址相同。加上就近原则,当实例属性中有对应的属性,会优先调用实例属性,如果没有,就会去原型中查找。那么我们要去判断这个属性是实例中的属性还是原型中的属性,有两个判断语法:hasOwnProperty() / inhasOwnProperty()是判断属性是否存在...