悟透Javascript之 原型prototype
构造函数的Prototype上定义的方法确实可以通过对象直接调用,而且代码是共享的。我表示我不懂。太难理解了,艹。
在Javascript中,prototype不但能让对象共享自己的财富,而且prototype还有寻根问祖的天性。
当从一个对象那里读取属性或调用方法时,如果该对象自身不存在这样的属性或方法,就会去自己关联的prototype对象里寻找。如果prototype没有,
又会去prototype自己关联的前辈prototype那里寻找,直到找到或追溯过程结束为止。
我们先从Javascript中的构造函数说起,
<script type="text/javascript">
function Person(name){//带参数的构造函数
this.name = name;//定义并初始化name属性
this.SayHello = function(){//定义对象方法SayHello
alert("Hello,I'm " + this.name);
}
} function Employee(name,salary)//子构造函数
{
Person.call(this,name);//调用父构造函数
this.salary = salary;//添加并初始化salary属性
this.ShowMeTheMoney = function(){
//添加对象方法ShowMeTheMoney
alert(this.name+" $"+this.salary);
}
}
var BillGates = new Person("Bill Gates");//创建Person对象
var SteveJobs = new Employee("Steve Jobs",9999);//创建Employee类的SteveJobs对象
BillGates.SayHello();//输出I'm Bill Gates
SteveJobs.SayHello();//输出I'm Steve Jobs
SteveJobs.ShowMeTheMoney();//Steve Jobs $9999 alert(BillGates.constructor == Person);//true
alert(SteveJobs.constructor == Employee);//true
alert(BillGates.SayHello == SteveJobs.SayHello);//false
</script>
这里的Employee继承了Person,包括属性设置和方法。但是这里的SayHello方法却不是一个方法,而是在Employee中新开辟的一个方法。相当于复制过来的方法。
而是用prototype就不是这样了。prototype可以让Employee共享Person的原型方法。
如果Person创建两个对象,那么它们调用同一个方法吗?
我们来看代码:
<script type="text/javascript">
function SayHello(){
alert("Hello,I'm "+this.name);
}
function Person(name){
this.name = name;
this.SayHello = SayHello;
}
var BillGates = new Person("Bill Gates");
var SteveJobs = new Person("Steve Jobs");
BillGates.SayHello();//Hello,I'm Bill Gates
SteveJobs.SayHello();//Hello,I'm Steve Jobs
alert(BillGates.SayHello==SteveJobs.SayHello);//true
</script>
结果发现,是的,它们的确调用一个方法。而不是像Employee那么复制出的新方法。
上述代码转化成原型模式,也很简单,如下所示,先设置属性,再通过原型定义方法:
<script type="text/javascript">
function Person(name){
this.name = name;//设置对象属性,每个对象各有一份属性数据
}
Person.prototype.SayHello = function(){//构造函数的Prototype上定义的方法确实可以通过对象直接调用,而且代码是共享的。我表示我不懂。太难理解了,艹。
alert("Hello,I'm "+this.name);
}
var BillGates = new Person("Bill Gates");
var SteveJobs = new Person("Steve Jobs");
BillGates.SayHello();//Hello,I'm Bill Gates
SteveJobs.SayHello();//Hello,I'm Steve Jobs
alert(BillGates.SayHello==SteveJobs.SayHello);//true </script>
"原型继承"是慈祥而又严厉的。原型对象将自己的属性和方法无私地贡献给孩子们使用,也并不强迫孩子们必须遵从,允许一些顽皮孩子按自己的兴趣和爱好独立行事。
我们来进一步研究原型prototype的特点,
<script type="text/javascript">
function Person(name){
this.name = name;
}
Person.prototype.company = "Microsoft";//原型的属性
Person.prototype.SayHello = function(){//原型的方法
alert("Hello,I'm "+this.name+" of "+this.company);
}
var BillGates = new Person("Bill Gates");
BillGates.SayHello();//由于继承了原型的东西,规规矩矩输出:Hello,I'm Bill Gates
var SteveJobs = new Person("Steve Jobs");
SteveJobs.company = "Apple";//设置了自己的company属性,掩盖了原型的company属性
SteveJobs.SayHello = function(){//实现了自己的SayHello方法,掩盖了原型的SayHello方法
alert("Hi, "+this.name+" like "+this.company+",ha ha");
}
BillGates.SayHello();//没有被改变,还是输出Hello,I'm Bill Gates of Microsoft
SteveJobs.SayHello();//原有的都被覆盖掉了,输出Hi, SteveJobs like Aplle,ha ha
</script>
这里原型中的属性和方法可以被覆盖掉。但原型自身的并没有受到影响。
对象可以掩盖原型对象的那些属性和方法,一个构造函数原型对象也可以掩盖上层构造函数原型对象既有的属性和方法。
我们可以随时给原型对象动态添加新的属性和方法,从而动态扩展基类的功能特性。我们来看下面的代码:
<script type="text/javascript">
function Person(name){//构造函数
this.name = name;
}
Person.prototype.SayHello = function(){//原型方法
alert("Hello,I'm "+this.name);
}
var BillGates = new Person("Bill Gates");//建立对象
BillGates.SayHello();
Person.prototype.Retire = function(){//对象后,动态扩展原型的方法
alert("Poor "+this.name+" ,byebye~!");
}
BillGates.Retire();//扩展的方法可以立刻使用
</script>
这里后续动态添加的方法,之前的对象已然可以使用,就是这么神奇。
最后我们用一个稍微复杂的例子来说明原型的使用:
<script type="text/javascript">
function Person(name){//构造函数
this.name = name;
}
Person.prototype.SayHello = function(){//原型方法
alert("Hello,I'm "+this.name);
}
//子类构造函数
function Employee(name,salary){
//Person.call(this,name);//调用上级的构造函数
this.name = name;
this.salary = salary;//扩展的成员属性
} //子类构造函数需要用上层构造函数来建立prototype对象
Employee.prototype = new Person();//继承了父类的prototype //子类定义自己的构造函数
Employee.prototype.ShowMeTheMoney = function(){
alert(this.name+" $"+this.salary);
} var BillGates = new Person("Bill Gates");
BillGates.SayHello();
//BillGates.ShowMeTheMoney();//不能用,因为Person的prototype里并没有这个方法 var SteveJobs = new Employee("Steve Jobs",1234);
SteveJobs.SayHello();//继承了Person的prototype方法
SteveJobs.ShowMeTheMoney();
alert(BillGates.SayHello == SteveJobs.SayHello);//True
</script>
这里的两个SayHello是同一个方法哦,也就是调用同一个方法产生的哦,跟之前的Employee复制过来的有区别哦。这点,读着可以细细体会其中的奥秘。
总之,原型prototype可以共享方法,"原型继承"是慈祥而又严厉的。原型对象将自己的属性和方法无私地贡献给孩子们使用,也并不强迫孩子们必须遵从,允许一些顽皮孩子按自己的兴趣和爱好独立行事。
悟透Javascript之 原型prototype的更多相关文章
- Javascript代码执行过程-《悟透Javascript》笔记
本文摘录自李战老师<悟透Javascript>一书的部分章节,为适应博客发表作了一点点修改. 1) 预编译分析. JavaScript执行引擎将所有定义式函数直接创建为作用域上的函数变量, ...
- 悟透JavaScript
要理解JavaScript,你得首先放下对象和类的概念,回到数据和代码的本原.前面说过,编程世界只有数据和代码两种基本元素,而这两种元素又有着纠缠不清的关系.JavaScript就是把数据和代码都简化 ...
- 悟透JavaScript(理解JS面向对象的好文章)
引子 编程世界里只存在两种基本元素,一个是数据,一个是代码.编程世界就是在数据和代码千丝万缕的纠缠中呈现出无限的生机和活力. 数据天生就是文静的,总想保持自己固有的本色:而代码却天生活泼,总想改变这个 ...
- (转载)悟透JavaScript
引子 编程世界里只存在两种基本元素,一个是数据,一个是代码.编程世界就是在数据和代码千丝万缕的纠缠中呈现出无限的生机和活力. 数据天生就是文静的,总想保持自己固有的本色:而代码却天生活泼,总想改变这个 ...
- javascript进阶-原型prototype
一.javascript原型认识 很多编程语言都有类的概念,我们可以拿原型和类进行比较,看看它们之间的区别以及相同点在哪里. 1.类:类是一个具体事物的抽象所以类是一个抽象的东西,在面向对象中类可以用 ...
- 悟透JavaScript(二)
初看原型 prototype源自法语,软件界的标准翻译为“原型”,代表事物的初始形态,也含有模型和样板的意义.JavaScript中的prototype概念恰如其分地反映了这个词的内含,我们不能将其理 ...
- 简单理解javascript的原型prototype
原型和闭包是Js语言的难点,此文主要讲原型. 每一个方法都有一个属性是 prototype 每一个对象都有一个属性是 _proto_ 一旦定义了原型属性或原型方法,则所有通过该构造函数实例化出来的所有 ...
- [js高手之路]一步步图解javascript的原型(prototype)对象,原型链
我们接着上文继续,我们通过原型方式,解决了多个实例的方法共享问题,接下来,我们就来搞清楚原型(prototype),原型链的来龙去脉. function CreateObj(uName) { this ...
- 悟透JavaScript (一)
首先说明,这是别人写的一篇文章,写得很好,对理解JavaScript很有好处,所以转帖过来. 引子 编程世界里只存在两种基本元素,一个是数据,一个是代码.编程世界就是在数据和代码千丝万缕的纠缠中 ...
随机推荐
- wget下载网站整个目录
wget -r -p -np -k -P ./data/ http://example.com/eg/ 具体参数: -P 表示下载到哪个目录 -r 表示递归下载 -np 表示不下载旁站连接 -k 表示 ...
- Linux下Tomcat安装、配置
/etc/profile./etc/profile.d和.bash_profile区别 /etc/profile和/etc/profile.d区别 .bash_profile 是存放用户的全局变量 / ...
- 第一篇:APUE-操作系统IO模型
操作系统IO模型 操作系统IO模型 声明:如下内容是根据APUE和mycat两本著作中关于I/O模式的一些内容加上自己的一些理解整理而成,仅供学习使用. 本节内容 UNIX下可用的五种I/O模型 ...
- PHP 给前面或者后面添加0补位
相信大家一定遇到这样的问题,因为PHP是弱类型的,所以进行排序的时候,有时候很胃疼 所以这里就需要将位数进行统一后进行处理 一般都是将末尾添加0进行补位 方法1 : str_pad — 使用另一个字 ...
- CoreAnimation3-专用图层
CAShapeLayer CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类.你指定诸如颜色和线宽等属性,用CGPath来定义想要绘制的图形,最后CAShapeLayer就自 ...
- 1 Winform 异步更新控件
刚才看到有人问为了winfrom中,在大数据绑定的时候出现画面假死的状态,为了解决这个问题希望通过再开一个线程来给控件绑定数据,可是画面还是会假死.现在看到的方法有1.掩耳盗铃法(Control.Ch ...
- jQuery 遍历同胞(siblings)
同胞拥有相同的父元素. 通过 jQuery,您能够在 DOM 树中遍历元素的同胞元素. 在 DOM 树中水平遍历 有许多有用的方法让我们在 DOM 树进行水平遍历: siblings() next() ...
- Input的readonly 属性与disabled属性
readonly 不可编辑,可以获得焦点,背景颜色默认灰色,值的字体颜色默认为灰色,值可以在请求中传递 disabled 不可编辑,不可以获得焦点,背景颜色默认灰色,值的字体颜色默认为灰色,值不可以在 ...
- group By 和 Union 、 Union all的用法
我学习的是MySQL,学习写sql语句过程中遇到Group By 和 Union. 大家乐意看这两个链接,写的很好 Group By: www.cnblogs.com/rainman/archive/ ...
- 水题(素数表)NYOJ素数距离
描述 现在给出你一些数,要求你写出一个程序,输出这些整数相邻最近的素数,并输出其相距长度.如果左右有等距离长度素数,则输出左侧的值及相应距离. 如果输入的整数本身就是素数,则输 ...