JavaScript的面向对象编程(OOP)(二)——原型
关于JavaScript的原型模式,下面的是学习后的个人理解,若是有偏差,还请指出,谢谢
JavaScript原型模式
1.什么是原型?
原型是一个对象,其他的对象可以通过它实现属性的继承,所有的对象在默认情况下都只有一个原型,而且原型本身也是一个对象。所以一个类的真正原型是被类内部的[prototype]属性所指出的。如下,我们先看一个空对象和它的原型
//定义一个空对象
function Person(){
}
Person.prototype.name = "username";
Person.prototype.getName = function(){
alert(this.name);//此处的this表示调用本方法的一个具体的实例化对象
}
这样,我们给一个Person的空的对象增加了一个原型属性name,和一个原型方法getName();通过 new Person().showName(); 能直接调用它的原型方法,并将原型属性name弹出。我们用对象集的方法表示原型
function Person(){
}
Person.prototype = {
name : "plum",
showName : function(){
alert(this.name);
}
}
这样便能清晰的表示出原型本身也是一个对象,并且被Person对象(此时这是一个类)所持有的属性prototype所指出。
2.那什么是对象呢?
在JavaScript中,一个对象就是任何的无序的键值对的集合,也就是除了五种的基本数据类型(number,string,boolean,null,undefined)其他的都是对象。
上述的例子中我们用functions定义的对象,那如果我们用var 或者new 直接创建的json对象和用构造函数实例化的对象又是怎么改变原型的引用的呢?
new Person().getName();//弹出username
var a = new Person();
a.__proto__.name = "v";//使用__proto__改变原型
a.getName();//弹出v
new Person().getName();//弹出v
通过上面一开始弹出的最开始的username,我们使用__proto__属性更改了原型模式之后再运行弹出v,由此我们可以知道使用new关键字的生成出来的对象都持有一个__proto__属性,这个属性保存了创建它的构造函数的prototype的原型的引用。
使用var直接创建的对象的原型引用
var cat = {}; //cat空类
Object.getPrototypeOf(cat).name = "plum";
cat.__proto__.master = "bote";
cat.age = 2;//隐式调用,cat.__proto__.age = 2,即隐藏了__proto__的调用
cat["sex"] = "man";
alert(cat.name+" "+cat.age+" "+cat["sex"]+" "+cat.master);//弹出plum 2 man bote
使用var直接创建的空类无法通过 cat.prototype.name = "plum" 方式来指向原型,只能通过Object.getPrototypeOf()或__proto__这两种方式显示调用 prototype而一般我们都是直接使用 cat.age或cat["age"]这两种隐式调用。
3.关于原型的继承
下面我们通过原型模式实现简单的继承
function per(){
this.getName = function(str){
alert(str);
};
}
per.prototype.getAge = function(age){
alert(age);
}
var a = {};//空对象,实现继承上面的类
a.__proto__= per.prototype;
a.getAge(2);
这种种方式实现的继承是简单继承,我们如果调用 a.getName("sad"); 此时a.getName is not function,并不能继承per内部的getName方法,所以这种继承是简单的继承,只有当被继承的类是空对象的时候,才能完全继承,只能继承Prototype的属性和方法。
下面我们用简单的方式实现继承
var b = {}; //空对象,是它完全继承上面的per(){}
b.__proto__ = new per();
//构造函数(constructor),将b的构造函数,变回他自己本身的构造函数
b.__proto__.constructor = b;
b.getAge(1);
b.getName("huahua");
这样种方式,我们便将per类完全继承过来了。
下面我们再来看一个完整的继承
//创建一个人员类
function Person(name){
this.name = name;
}
//创建教师类
function Teacher(name,books){
//call方法可以将一个函数的对象上下文从初始化变成由this来决定
//调用Person的构造函数,因为Person没有new,所以它是个空对象
Person.call(this,name);
this.books = books;
}
//使老师继承人员类
Teacher.prototype = new Person();
Teacher.prototype.constructor = Teacher;
Teacher.prototype.getBooks = function(){
return this.name + " " + this.books;
}
var jim = new Teacher("Tom","JavaScript");
alert(jim.getBooks());
Teacher继承了Person,在原型中添加了getBooks的方法。
我们也可以写出Extend的方法,实现所有的继承
function extend(subClass,superClass){
//1.子类的原型类属性等于父类的原型属性
//初始化一个中间空对象,为了转换子父类关系
var F = function(){};
F.prototype = subClass.prototype;
//2.让子类继承F
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
//3.为子类增加superClass的属性
subClass.superClass = superClass.prototype;
//4.如果原型类是超类(object),也要把构造函数的级别降下来
if(subClass.prototype.constructor == Object.prototype.constructor){
superClass.prototype.constructor = subClass;
}
}
这样我们通过这和extend方法能直接实现继承,下面我们使用这个方法来测试效果
function Author(name,books){
Author.superClass.constructor.call(this,name);
this.books = books;
this.getBook = function(){
return this.name + " " + this.books;
}
}
extend(Author,Person);
var peter = new Author("Peter","javascript");
alert(peter.getBook());
这样,以后便能用extend的方式直接继承,要注意,JavaScript中无法实现多继承。
关于继承的问题尽量都在代码和代码描述里,要在实例中理解,不能只看概念,不然只能是云里雾里,有疑问的地方多敲一下测试代码,就能理解。
JavaScript的面向对象编程(OOP)(二)——原型的更多相关文章
- JavaScript的面向对象编程(OOP)(一)——类
在学习JavaScript面向对象的编程之前,需要知道,并了解面向对象的一些基本的常识.初学者中大多数都以为面向对象中,面向对象的编程是很重要和占据很大一部分精力.笔者在之前也是认为OOP是面向对象的 ...
- JavaScript面向对象编程(二)构造函数和类
new关键字和构造函数 在文章JavaScript面向对象编程(一)原型与继承中讨论啦JavaScript中原型的概念,并且提到了new关键字和构造函数.利用new关键字构造对象的实例代码如下: // ...
- Javascript面向对象编程(二):构造函数的继承 作者:yuan一峰
Javascript面向对象编程(二):构造函数的继承 作者: 阮一峰 日期: 2010年5月23日 这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生 ...
- JavaScript 面向对象编程(二):继承
Javascript面向对象编程(二):构造函数的继承 这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例. 今天要介绍的是,对象之间的"继 ...
- JS--我发现,原来你是这样的JS:面向对象编程OOP[3]--(JS继承)
一.面向对象编程(继承) 这篇博客是面向对象编程的第三篇,JS继承.继承顾名思义,就是获取父辈的各种"财产"(属性和方法). 怎么实现继承? 我们的JavaScript比较特别了, ...
- JavaScript--我发现,原来你是这样的JS:面向对象编程OOP[2]--(创建你的那个对象吧)
一.介绍 我们继续面向对象吧,这次是面向对象编程的第二篇,主要是讲创建对象的模式,希望大家能从博客中学到东西. 时间过得很快,还是不断的学习吧,为了自己的目标. 二.创建对象 1.前面的创建对象方式 ...
- JS--我发现,原来你是这样的JS:面向对象编程OOP[2]--(创建你的那个对象吧)
一.介绍 我们继续面向对象吧,这次是面向对象编程的第二篇,主要是讲创建对象的模式,希望大家能从博客中学到东西. 时间过得很快,还是不断的学习吧,为了自己的目标. 二.创建对象 1.前面的创建对象方式 ...
- js面向对象编程(二)构造函数的继承(转载)
Javascript面向对象编程(二):构造函数的继承 这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例. 今天要介绍的是,对象之间的"继 ...
- 学习面向对象编程OOP 第一天
面向对象编程 Object Oriented Programming 一.什么是面向对象编程OOP 1.计算机编程架构; 2.计算机程序是由一个能够起到子程序作用的单元或者对象组合而成.也就是说由多个 ...
- S.O.L.I.D 是面向对象设计(OOD)和面向对象编程(OOP)中的几个重要编码原则
注:以下图片均来自<如何向妻子解释OOD>译文链接:http://www.cnblogs.com/niyw/archive/2011/01/25/1940603.html < ...
随机推荐
- 【转】Source Insight的Alt + W键不能使用的解决办法
转载地址:http://velep.com/archives/607.html 对于Source Insight 3.5,习惯于使用Alt + W组合键并配合数字键来切换文件窗口,带来无比的便利.但是 ...
- 三元运算与lambda表达式
#三元运算,就是对if else的简写 if 1 == 1: print("jasper") else: print("sb") 三元运算写法 name=&qu ...
- 使用AFNetWorking读取JSON出现NSCocoaErrorDomain Code=3840的解决方法
最近在使用AFNetworkWorking读取JSON时,出现了NSCocoaErrorDomain Code=3840的错误.这种错误应该是服务器端返回JSON格式不对造成的.通过Google搜到这 ...
- asp.net type=file在上传图片到服务器
前台 <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> ...
- eclipse 4.5.2 源码修改 格式化Java代码
注:本文代码基于eclipse4.5.2 1. 需求:在换电脑之后,如何不用配置eclipse就可以很快进入开发呢,并保持原来的编码规范. 2. 方法:修改eclipse源码 分别修改了两个jar包2 ...
- HQL查询——HQL查询的基本用法
HQL查询--HQL查询的基本用法 1.HQL语法类似于SQL语法,但是需要注意的是,HQL是一种完全面向对象的查询语言.SQL语言操作的对象是数据表.列等数据库对象,而HQL语言的操作对象是类.实例 ...
- LINQ之路 9:LINQ to SQL 和 Entity Framework(上)
在上一篇中,我们从理论和概念上详细的了解了LINQ的第二种架构“解释查询”.在这接下来的二个篇章中,我们将使用LINQ to SQL和Entity Framework来实践“解释查询”,学习这些技术的 ...
- jQuery index()
index() index() 方法返回指定元素相对于其他指定元素的 index 位置. 语法 $(selector1).index(selector2) selector2:可选,指定元素:为空时默 ...
- 01 初识python
python.exe -v / python3 -v安装python3时, 会得到一个 IDLE(提示符>>>), 简单, 有用, 包含语法编辑器(颜色可变), 调试工具, pyth ...
- JavaScript中的编码函数
JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decod ...