JavaScript 类式继承与原型继承
交叉着写Java和Javascript都有2年多了,今天来总结下自己所了解的Javascript类与继承。
Javascript本身没有类似Java的面向对象的类与继承术语,但其基于原型对象的思想却可以轻松实现各种类和继承。
下面来描述实现类的第一种方法,请看例子:
function People(name, age){
this.name = name;
this.age = age;
this.say = function(){
console.log('hello, javascript!');
};
}
var people = new People('sky',25);
people.say();
从形式上看上去,与面向对象的类几乎一样,this为实例化后的对象自身,name/age为成员变量,say为成员方法,但其内部原理却相差甚远。
接下来分析其中的不同之处,先看一下代码:
var people_1 = new People('sky1',21);
var people_2 = new People('sky2',22);
people_1.say == people_2.say//false
按照面向对象语言的特征,表面上看上去people_1/2都有自己的属性name/age,有公共的(占用同一份内存区域)方法say,但在JS中并非如此。
首先,People自身是一个对象,new People产生了两个对象people_1/2,每个对象都拥有各自的内存空间,即将name/age/say在各自空间都存在一份。
可通过 people_1.say == people_2.say 验证,结合下图可清楚得出结论,每个对象之间是独立的个体,没有关联关系。

接下来,结合JS原型概念构造类的第二种方法。原型是JS的核心概念,后续篇章详细描述。
function People(name,age){
this.name=name;
this.age=age;
}
People.prototype.say = function(){
console.log('hello, javascript!');
};
var people_1 = new People('sky1',21);
var people_2 = new People('sky2',22);
people_1.say == people_2.say//true
通过看到上述代码结果,可得出people_1/2共享成员say,可通过下图分析。这里涉及到了原型链的概念,后面和原型一起阐明。

关于类的构造就介绍到这。接下来描述实现继承的几种方法。
先来看第一种,基于类式继承的方式。
function People(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
this.say=function(){
console.log('hello,javascript!');
};
}
function Man(name,age){
People.call(this,name,age,'male');
}
function Woman(name,age){
People.call(this,name,age,'female');
}
var man = new Man('sky-man',21);
var woman = new Woman('sky-woman',22);
man.say();
woman.say();
这种继承基于第一种类的构造形式,即采用复制的方法实现子类对象对父类成员的继承。
其中,起复制作用的关键在与People.call(this,...)语句上,意思是使用call方法借用People函数来构造Man对象。
这里不太好理解,首先要理解call方法如何使用,其次要了解this作用域的概念和使用。关于作用域及作用域链概念也在以后的篇章中阐述。
总之,这里的意义是将People对象的属性复制到Man对象上。
我们看下这里的图形描述:

很显然man/woman都继承了People的成员变量,但其采用的是复制的方法,对象之间并没有建立真正的继承。
接下来将基于第二种构造类的方法来介绍第二种构造类的形式,即继承依赖原型。直接看一下代码:
function People(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
}
People.prototype.say=function(){
console.log('hello,javascript!');
}
function Man(name,age){
People.call(this,name,age,'male');
}
Man.prototype = Object.create(People.prototype);
function Woman(name,age){
People.call(this,name,age,'female');
}
Woman.prototype = Object.create(People.prototype);
上面的代码可能已经引入一些JS原理层面的东西,还是先用图来展示:

上图中引入几个比较JS原理的东西,prototype/constructor/__proto__,其中前两者是JS标准中存在的,
而__proto__是标准中未暴露的,该名称采用chrome暴露的属性名。
其中prototype是原型函数,每个函数中都存在;constructor是构造器,每个对象都存在;__proto__是原型对象,每个对象都存在。
此处先介绍到这,后期将根据ECMAScript标准详细介绍几者之间的关系。
通过上面的线条可以了解每个对象之间的关系,以及原型链在其中所起的作用。
可以看出,第二种继承方法是基于原型的,虽然成员是采用复制的方式,但保证了方法的继承性。这与传统面向对象类继承意义上才是一致的。
通过上面的类的构造和继承方式,我们对Javascript原型继承有一定了解。那么如果要实现内部成员,内部方法,该如何实现呢?
疑问将在下个篇章解答。
JavaScript 类式继承与原型继承的更多相关文章
- javascript类式继承最优版
直接看实例代码: <!doctype html> <html lang="en"> <head> <meta charset=" ...
- javascript类式继承模式#4——共享原型
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- javascript类式继承模式#3——借用和设置原型
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- javascript类式继承模式#2——借用构造函数
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- JS面向对象组件 -- 继承的其他方式(类式继承、原型继承)
继承的其他形式: •类式继承:利用构造函数(类)继承的方式 •原型继承:借助原型来实现对象继承对象 类 : JS是没有类的概念的 , 把JS中的构造函数看做的类 要做属性和方法继承的时候,要分开继 ...
- javascript类式继承模式#1——默认模式
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- javascript类式继承函数最优版
直接上代码: klass函数 var klass = function (Parent, props) { var Child, F, i; //1.新构造函数 Child = function () ...
- JS高级. 03 混入式继承/原型继承/经典继承、拓展内置对象、原型链、创建函数的方式、arguments、eval、静态成员、实例成员、instanceof/是否在同一个原型链
继承:当前对象没有的属性和方法,别人有,拿来给自己用,就是继承 1 混入式继承 var I={ }; var obj = { name: 'jack', age:18, sayGoodbye : fu ...
- JavaScript内置对象与原型继承
(一) 理解JavaScript类定义 1>关于内置对象理解 console.log(Date.prototype.__proto__===Object.prototype //tru ...
随机推荐
- git 学习笔记2--How to create/clone a repository
1. create/clone 1.1 create 针对已经存在的目录创建一个repository,使用以下命令: git init Initialized empty Git repository ...
- Oracle 查询性能优化实践
1.索引使用原则 不要对索引使用全模糊,但是 LIKE 'asdf%'是可以的,即不要Contains,可用StartWith 不要对索引进行函数,表达式操作,或者使用is null判断,否则 ...
- 新提交审核app保留检查更新入口将被拒绝(读取App Store 版本号的)
3月起要求关闭所有App内的检查更新功能,苹果App Store将向用户自动提示更新,新版本提交审核版本如果保留检查更新入口,审核时,将被拒绝. 以上拒绝的方案: 读取App Store的版本号. 替 ...
- 【BZOJ】3916: [Baltic2014]friends
http://www.lydsy.com/JudgeOnline/problem.php?id=3916 #include <bits/stdc++.h> using namespace ...
- 【BZOJ】3065: 带插入区间K小值
http://www.lydsy.com/JudgeOnline/problem.php?id=3065 题意:带插入.修改的区间k小值在线查询.(原序列n<=35000, 询问<=175 ...
- SQL 学习笔记
1.判断数据库中某个值是否为null(而不是'null',空字符串'',若干个空格' ') 一定不能用=null 或 !=null,而要用is null 或 is not null. 2.在sqlse ...
- css learn
float: 1.margin属性本身与float无关.写不写float都可以margin. 2.top,right,bottom,left和z-index都无法使用. 3.父元素浮动,子元素在其中仍 ...
- spring源码学习之路---环境搭建(一)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 最近已经开始了spring源 ...
- HDU 1710 二叉树遍历,输入前、中序求后序
1.HDU 1710 Binary Tree Traversals 2.链接:http://acm.hust.edu.cn/vjudge/problem/33792 3.总结:记录下根结点,再拆分 ...
- IOS UINavigationController 导航控制器
/** 导航控制器掌握: 1.创建导航控制器 UINavigationController *nav = [[UINavigationController alloc] initWithRootVie ...