We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在大多数面向对象编程语言中,继承是基于类来实现的,但是在JavaScript中是基于原型链来实现的,何为原型链,今天我们一步一步来解析它。
我们首先来创建两个函数对象,并且希望子类型能继承父类型的某些方法,代码如下,很简单:
<script> //父类型 function Supper() { this.supProp = "Supper Property"; } Supper.prototype.showSupperProperty = function() { console.log(this.supProp); } //子类型 function Sub() { this.subProp = "Sub Property"; } Sub.prototype.showSubProperty = function() { console.log(this.subProp); } </script>
这段代码会在内存空间中有如图所示的内存分配:
想要实现继承,我们根据 实例的隐式原型对象指向构造函数的显示原型对象 可知,要想要Sub的实例能访问Supper原型对象中的showSupperProperty函数对象,必须有一条原型链能指向上图中地址为0x234的Object实例对象,我们先假如有一个Supper的实例对象已经创建,在图中体现如下:
Sub
Supper
showSupperProperty
0x234
Object
好了,我们先不急,先创建一个Sub的实例看看,他在内存中如何指向的,在上述代码之后添加
var sub = new Sub();
有如下内存分配:
根据上图来说,我们的Sub的实例sub并没有与Object构成原型链,无法访问到Supper原型中的showSupperProperty方法,那我们到底该怎么呢?
sub
首先我们要清楚一点,sub.__proto__的值是怎么来的,Sub函数对象在定义时就已经有了Sub.prototype,而sub.__proto__是由Sub.prototype传递地址值给它而得到的值。我们要让sub._ ``_proto__`` === (Supper的某一个实例对象)不可以构成原型链了吗,需要下面关键的一句话:
sub.__proto__
Sub.prototype
sub._ ``_proto__`` === (Supper的某一个实例对象)
Sub.prototype = new Supper();
这句话需要在子类型创建之后立马写上,为什么?你看之后画的图就知道了。 现在内存图如下:
由图已经可得到,有一条完整的原型链,故现在子类型的实例对象可以访问父类型的原型中的方法了。 若我们的
Sub.prototype.showSubProperty = function() { console.log(this.subProp); }
不在Sub.prototype = new Supper();之后,那就等于白白丢掉了。。因为原来所指向的Object对象已经成为了垃圾对象。所以,完整的代码如下:
<script> //父类型 function Supper() { this.supProp = "Supper Property"; } Supper.prototype.showSupperProperty = function() { console.log(this.supProp); } //子类型 function Sub() { this.subProp = "Sub Property"; } //子类型的原型为父类型的一个实例对象 Sub.prototype = new Supper(); //让子类型的原型的constructor指向子类型 Sub.prototype.constructor = Sub; Sub.prototype.showSubProperty = function() { console.log(this.subProp); } var sub = new Sub(); sub.showSupperProperty(); sub.showSubProperty(); </script>
得到完整图如下:
控制台输出验证了其正确性:
结语:这就是原型链继承了,图还是要多画多看几遍的,好好理解一下很有帮助。
下面简单给一个组合继承的代码,算是模板代码了,本身是借用构造函数继承(应该不能叫真正意义上的继承)和原型链继承的组合,重点是原型链继承,以上已经详细讲述:
<script> function Person(name, age) { this.name = name; this.age = age; } Person.prototype.setName = function(name) { this.name = name; } function Student(name, age, price) { Person.call(this, name, age); //为了得到属性 this.price = price; } Student.prototype = new Person();//为了能看到父类型的方法 Student.prototype.constructor = Student;//修正constructor属性 Student.prototype.setPrice = function(price) { this.price = price; } var stu1 = new Student('Bob', 18, 16000); stu1.setName('Jack'); stu1.setPrice(20000); console.log(stu1.name, stu1.age, stu1.price); </script>
The text was updated successfully, but these errors were encountered:
No branches or pull requests
原型链继承详解
前言
在大多数面向对象编程语言中,继承是基于类来实现的,但是在JavaScript中是基于原型链来实现的,何为原型链,今天我们一步一步来解析它。
两个函数对象,父类型和子类型
我们首先来创建两个函数对象,并且希望子类型能继承父类型的某些方法,代码如下,很简单:
这段代码会在内存空间中有如图所示的内存分配:
![Untitled1.png](https://camo.githubusercontent.com/7c65a05f6767b6004b8a40780c7e5b25851fba55a43630875afb0687c77a664a/68747470733a2f2f63646e2e6e6c61726b2e636f6d2f79757175652f302f323031392f706e672f3334313331342f313536303836313839343533322d33353434613935652d376463652d346536312d616233392d6262626530613862663461332e706e6723616c69676e3d6c65667426646973706c61793d696e6c696e65266865696768743d353338266e616d653d556e7469746c6564312e706e67266f726967696e4865696768743d353338266f726967696e57696474683d3733302673697a653d3534343633267374617475733d646f6e652677696474683d373330)
想要实现继承,我们根据 实例的隐式原型对象指向构造函数的显示原型对象 可知,要想要
![Untitled1 (1).png](https://camo.githubusercontent.com/fdd3cd894f65c700d4fa172db1b847b4a397985bc337ea682289de8c80c37468/68747470733a2f2f63646e2e6e6c61726b2e636f6d2f79757175652f302f323031392f706e672f3334313331342f313536303836323732373331322d37373762616537312d383262352d346432332d613866352d6161656463316365323561642e706e6723616c69676e3d6c65667426646973706c61793d696e6c696e65266865696768743d353338266e616d653d556e7469746c656431253230253238312532392e706e67266f726967696e4865696768743d353338266f726967696e57696474683d3733302673697a653d3635303033267374617475733d646f6e652677696474683d373330)
Sub
的实例能访问Supper
原型对象中的showSupperProperty
函数对象,必须有一条原型链能指向上图中地址为0x234
的Object
实例对象,我们先假如有一个Supper
的实例对象已经创建,在图中体现如下:好了,我们先不急,先创建一个
Sub
的实例看看,他在内存中如何指向的,在上述代码之后添加有如下内存分配:
![Untitled1 (2).png](https://camo.githubusercontent.com/d2b9d6a214e0ed129704cc7329bd1695d20f9e6cf9192d453c17c96ffa697c3b/68747470733a2f2f63646e2e6e6c61726b2e636f6d2f79757175652f302f323031392f706e672f3334313331342f313536303836333333393133322d31333861343162392d353561362d346564362d626435642d6338613761383239363639352e706e6723616c69676e3d6c65667426646973706c61793d696e6c696e65266865696768743d373033266e616d653d556e7469746c656431253230253238322532392e706e67266f726967696e4865696768743d373033266f726967696e57696474683d3733302673697a653d3832343937267374617475733d646f6e652677696474683d373330)
根据上图来说,我们的
Sub
的实例sub
并没有与Object
构成原型链,无法访问到Supper
原型中的showSupperProperty
方法,那我们到底该怎么呢?首先我们要清楚一点,
sub.__proto__
的值是怎么来的,Sub
函数对象在定义时就已经有了Sub.prototype
,而sub.__proto__
是由Sub.prototype
传递地址值给它而得到的值。我们要让sub._ ``_proto__`` === (Supper的某一个实例对象)
不可以构成原型链了吗,需要下面关键的一句话:这句话需要在子类型创建之后立马写上,为什么?你看之后画的图就知道了。
![Untitled1 (3).png](https://camo.githubusercontent.com/1dfaf203c25fb6207eb7cfcbdca3654dd25c024306f8ceff62d9722250b43692/68747470733a2f2f63646e2e6e6c61726b2e636f6d2f79757175652f302f323031392f706e672f3334313331342f313536303836343630343131342d62393462343966302d656536642d346536382d623566622d3330373435333764383330302e706e6723616c69676e3d6c65667426646973706c61793d696e6c696e65266865696768743d373036266e616d653d556e7469746c656431253230253238332532392e706e67266f726967696e4865696768743d373036266f726967696e57696474683d3733332673697a653d3837383834267374617475733d646f6e652677696474683d373333)
现在内存图如下:
由图已经可得到,有一条完整的原型链,故现在子类型的实例对象可以访问父类型的原型中的方法了。
若我们的
不在
Sub.prototype = new Supper();
之后,那就等于白白丢掉了。。因为原来所指向的Object对象已经成为了垃圾对象。所以,完整的代码如下:得到完整图如下:
![Untitled1 (4).png](https://camo.githubusercontent.com/e1d9e5cc37d001378b6d3111919250f26633afcfdc93a5d5e366ea67eb7dddf9/68747470733a2f2f63646e2e6e6c61726b2e636f6d2f79757175652f302f323031392f706e672f3334313331342f313536303836343938343431312d62386434663233332d663965352d343963642d626462312d3662383663326466313132392e706e6723616c69676e3d6c65667426646973706c61793d696e6c696e65266865696768743d373036266e616d653d556e7469746c656431253230253238342532392e706e67266f726967696e4865696768743d373036266f726967696e57696474683d3733332673697a653d3931313035267374617475733d646f6e652677696474683d373333)
控制台输出验证了其正确性:
结语:这就是原型链继承了,图还是要多画多看几遍的,好好理解一下很有帮助。
下面简单给一个组合继承的代码,算是模板代码了,本身是借用构造函数继承(应该不能叫真正意义上的继承)和原型链继承的组合,重点是原型链继承,以上已经详细讲述:
The text was updated successfully, but these errors were encountered: