首页 > 编程语言 >《悟透javascript》学习笔记:X、深入继承

《悟透javascript》学习笔记:X、深入继承

时间:2022-12-08 11:03:07浏览次数:40  
标签:__ function person 继承 javascript 笔记 Person 对象 prototype


引言

 

      JavaScript不是按面向对象的思想设计的程序语言,所以它不具备像现有的面向对象的语言那样的功能,但是面向对象的思想是如此的深入人心,以至于JavaScript也削尖了脑袋“面向对象”。果真,通过一些特殊的处理,JavaScript也具有了基本的面向对象的功能。

 

function、new、prototype与constructor

 

      看代码:

 

<script language="javascript">
function Person(name){
this.name=name;
this.showMe=function(){
alert(this.name);
}
};
var one=new Person('JavaScript');
one.showMe();
</script>

 

很多人见到了久违的new操作符,于是就叫Person为“类”,可是又没有关键字class的出现,觉得叫“类”有点勉强。于是退而求其次叫Person为类的构造函数。这些概念好像都没有错,之所以出现这样的情况,可能是因为大家都学习了传统的面向对象语言(c++,c#,java等),还有一种思维定势吧。为了让javascript也面向对象,要在javascript中找到与传统面向对象语言的影子。可是按照javascript的说法,function定义的这个Person就是一个Object(对象),而且还是一个很特殊的对象,这个使用function定义的对象与使用new操作符生成的对象之间有一个重要的区别。这个区别就是function定义的对象有一个prototype属性,使用new生成的对象就没有这个prototype属性。

 

prototype属性又指向了一个prototype对象,注意prototype属性与prototype对象是两个不同的东西,要注意区别。在prototype对象中又有一个constructor属性,这个constructor属性同样指向一个constructor对象,而这个constructor对象恰恰就是这个function函数本身。有点头晕,看下图吧:

 

 

      下面举例证明:

<script language="javascript">
function Person(name){
this.name=name;
this.showMe=function(){
alert(this.name);
}
};
var one = new Person('JavaScript');
//结果undefined,证明new出的对象无prototype属性
alert(one.prototype);
//结果object,证明function定义的对象有prototype属性
alert(typeof Person.prototype);
//结果true,证明function定义的对象prototype的constructor属性指向的对象就是function定义的对象
alert(Person.prototype.constructor == Person)
</script>

 

对象创建三部曲与__proto__属性

 

      看代码:

<script language="javascript">
function Person(name){
this.name=name;
this.showMe=function(){
alert(this.name);
}
}
Person.prototype.say = function(){alert("i'm from prototype");}

var one = new Person('JavaScript');
one.showMe();
one.say();
</script>

      上面可以看到,不论是showMe还是say方法,我们都可以调用到。要解释这个结果就要仔细研究一下new这个操作符了,实际上对象的创建可以分为三个步骤:

1.       var one = {};  这是创建对象one

2.       one.__proto__ = Person.prototype;  这是将步骤1所创建的对象的“隐式链”设置成person的原型对象。“__proto__”被称为“隐式链”,不对外开放,但firefox浏览器对外开放,如果要实验请到firefox上实验。隐式链上的方法和属性是通过对象名直接访问的,所有对象都有“隐式链”,通过这一步,one对象就拥有了Person.prototype下的所有属性和方法,可以通过one直接访问。

3.       Person.call(one);  这是将步骤1所创建的对象one作为person构造函数的this并调用person函数。这样one对象的this就拥有了person构造函数中的所有属性和方法。

 

其中第二步中出现了一个新名词就是“隐式链”(__proto__属性), __proto__指向了函数Person的prototype对象。在person的prototype对象中出现的任何属性或者函数都可以在one对象中直接使用,这个就是javascript中的原型继承了。又头晕了,上图吧!

 

 

 

这样one对象通过内置的原型对象 (__proto__属性)就可以直接访问Person的prototype对象中的任何属性与方法了。这也就解释了上面的代码中为什么one可以访问from函数了。因为prototype对象中有一个constructor属性,那么one也可以直接访问constructor属性。代码:

 

<script language="javascript">
function Person(name){
this.name=name;
this.showMe=function(){
alert(this.name);
}
}
Person.prototype.say = function(){alert("i'm from prototype");}

var one = new Person('JavaScript');
//结果true,证明上面所说的one.__proto__ = Person.prototype;是成立的
alert(one.constructor == Person.prototype.constructor);
alert(one.constructor);
alert(Person.prototype.constructor);
//结果“JavaScript”,证明上面所说的Person.call(one);是成立的
alert(one.name);
</script>

 

继承的实现

 

      看代码:

<script language="javascript">
function person(name){
this.name=name;
this.showMe=function(){
alert(this.name);
}
}
person.prototype.say = function(){alert("i'm from prototype");}

function employee(){
}
employee.prototype = new person();

var bill = new employee();
bill.say();
//结果为true,原因是bill.__proto__=person.prototype
alert(bill.constructor == person.prototype.constructor);
alert(bill.constructor);
</script>

 

继承的实现很简单,只需要把子类的prototype设置为父类的一个对象即可。注意这里说的可是对象哦!(就是必须用new)那么通过prototype属性实现继承的原理是什么呢?还是先看图形说明,然后编写代码进行验证。

 

 

 

      ­­­­__proto__是隐式链,所有对象都有__proto__属性,__proto__所属对象可以直接访问其下的属性和方法,__proto__属性的指向决定了对象可以访问哪里方法和属性。

 

      上图不知道大家是否能够理解,最重要的是中间两个的关系似乎不那么好理解,因为之前所说的new可以理解为:

1          employee.prototype.__proto__ = person.prototype

2          person.call(employee.prototype)

我们最重要的是改变了employee.prototype的__proto__属性,关键就在这里,__proto__指向person.prototype后employee.prototype做拥有的所有东西都会丢失,取而代之的是person.prototype,或者说用new person()对象替代了employee.prototype对象更好理解。反过来也可以说只要__proto__的指向改变了就说明使用了new

 

      好了,下面就解释为什么这样就模拟了面向对象的类的继承。首先来看bill对象,它是由employee构造函数创建而来,但它却可以使用person的prototype下的方法,我们根据上图来一步步查找。首先,在bill对象中查找,然后到bill对象的__proto__所指向的对象employee.prototype对象(new person()对象)查找,再到employee.prototype对象的__proto__所指向的person的prototype对象中查找,结果say方法就在person的prototype对象中找到了,然后调用它。如果划分为步骤则如下:

1          bill = new employee(); //就先在employee()构造函数中查找

2          bill.__proto__ = employee.prototype = new person(); //在employee.prototype中查找,也就是在new person()对象中查找

2.1        employee.prototype.__proto__ = person.prototype;  //在person.prototype中查找

2.2        person.prototype.__proto__ = object.prototype; //在object.prototype中查找

 

这样的一个过程不就是模拟了类的继承吗?也许是我自己的思路还不够清晰,所以我的描述也只能到此为止了。

 

标签:__,function,person,继承,javascript,笔记,Person,对象,prototype
From: https://blog.51cto.com/u_15906220/5920743

相关文章

  • 再读《悟透javascript》之五、五子棋
    前言     五子棋是个很有趣的游戏,在用javascript开发之后,我发现其实ai算法才是最难的,这里的ai算法是直接借鉴自其它的ai算法。  代码如下:<htmlxmlns="http://www.w3......
  • java爬虫笔记:使用WebCollector增量采集www.baiduyunsousou.com
    WebCollector可以配置短点爬取,历史数据根据Key去重,也就是url 最近在采集百度云网盘,记录一下 /***@authorLiu*@create2022-08-0211:48*/@Component@Slf......
  • 《悟透javascript》学习笔记:四、函数的魔力
    引言 JavaScript的代码就只有function一种形式,function就是函数的类型。也许其他编程语言还有procedure或method等代码概念,但在JavaScript里只有function一种形......
  • 再读《悟透javascript》之四、贪吃蛇
    前言     贪吃蛇是个很简单的小游戏,但是却很有趣,下面是我用JavaScript写的一个贪吃蛇的代码:  代码如下:   <htmlxmlns="http://www.w3.org/1999/xhtml"><headr......
  • 《悟透javascript》学习笔记:一、前言
    《悟透JavaScript》学习笔记  这是一本很形象生动的书,使我们可以更深地了解了JavaScript。 引言   编程世界里只存在两种基本元素,一个是数据,一个是代码。编程世界就......
  • 《悟透javascript》学习笔记:二、回归简单
    引言 要理解JavaScript,你得首先放下对象和类的概念,回到数据和代码的本原。前面说过,编程世界只有数据和代码两种基本元素,而这两种元素又有着纠缠不清的关系。JavaScript就......
  • 《悟透javascript》学习笔记:三、似类却不是类
    引言 JavaScript没有“类”的概念!这让很多学习过高级语言的人感到很不爽,其实比之于C语言又如何呢?显然JavaScript要比C语言好用很多。 不废话,上代码 <scriptlanguage="j......
  • 再读《悟透javascript》之三、甘露模型
    前言     甘露模型是用于开发基于javascript的类库的,通过它,我们可以以类似C#等面向对象的语言式的模式来开发javascript类库,这将使你的javascript代码变得清晰有条理......
  • 「Note」《一些特殊的数论函数求和问题》学习笔记
    其实可以分成三个独立部分的,但是懒了所以全放一起。Min_25筛Meissel-Lehmer算法拟合平面曲线参考一些特殊的数论函数求和问题朱震霆国家集训队论文2018《一些特......
  • C++的语法 学习笔记1
    C++的语法学习笔记1  C++各种数据类型的默认值数值类型int/double/float/long0char'\0'string"\0"bool0,也就是false  数......