js 中的原型链与继承
ECMAScript中将原型链作为实现继承的主要方法,其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
1、原型链
先回忆一下构造函数和原型以及实例的关系:每个构造函数都有一个原型对象,原型对象中有一个指向构造函数的指针,而所有实例都有一个指向原型对象的内部指针。
那么实现 原型链的具体操作是这样的:让构造函数的原型对象等于另一个类型的实例。此时,原型对象将包含一个指向另一个原型的指针,另一个原型中也包含这一个指向另一个构造函数的指针。
如果另一个原型又是再另一个类型的实例的话,依然存在上述关系,如此层层递进,就构成一个链条,即为原型链。
通过原型链继承实例:
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
}
function SubType(){
this.subproperty = false;
}
SubType.prototype = new SuperType(); // 重写原型,继承
SubType.prototype.getSubValue = function(){
return this.subproperty;
}
var instance = new SubType();
console.log(instance.getSuperValue()); //true
console.log(instance.getSubValue()); //false
原型链关系图

出现Object的原因是:所有引用类型默认都继承了Object,而且也是通过原型链继承的。
2、继承
上面的例子就是一个仅仅使用原型继承的例子,但仅仅使用原型继承会共享所有属性和方法,也不能在不影响所有对象实例的情况下向超类的构造函数传递参数。下面介绍其他继承方式。
2.1 仅通过构造函数继承
function SuperType(name){
this.name= name;
this.colors = ["red","blue","green"];
}
function SubType(){
SuperType.call(this,"tom");
this.age = 29;
}
var instance = new SubType();
console.log(instance.age); //
console.log(instance.name); // tom
这种方法需要用到 apply() 或 call() 函数。
能有自己的特性,也可以传递参数给超类。但超类的原型中的属性和方法对子类是不可见的(访问不到)。
2.2 构造函数和原型组合继承
function SuperType(name){
this.name= name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name,age){
SuperType.call(this,name); //执行new SubType(name,age)时,第二遍执行 SuperType(),子类对象实例将包含超类构造函数的属性
this.age = age;
}
// 对象实例的原型会包含超类构造函数的属性,还有超类构造函数原型的属性
SubType.prototype = new SuperType(); // 第一遍执行 SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function (){
console.log(this.age);
}
var instance1 = new SubType("tom",29);
instance1.colors.push("black");
console.log(instance1.colors); // ["red", "blue", "green", "black"]
instance1.sayName(); // tom
instance1.sayAge(); //
var instance2 = new SubType("jack",32);
console.log(instance2.colors); // ["red", "blue", "green"]
instance2.sayName(); //jack
instance2.sayAge(); //
这种方法比较常用。
2.3 原型式继承
function createObject(o){
function F(){};
F.prototype = o;
return new F();
}
var person = {
name: "Tom",
friends:["Shelby","Court","Van"]
}
var p1 = createObject(person);
p1.name = "Greg";
p1.friends.push("Rob");
var p2 = createObject(person);
p2.name = "Linda";
p2.friends.push("Barbie");
console.log(person.friends); // ["Shelby", "Court", "Van", "Rob", "Barbie"]
这种方法的核心是:将已有的对象作为新对象的原型,相当于继承。这种继承比较简单,方便。
可以将上面的新修改一下,在已有对象的基础上给新对象添加新属性。
function createObject(o){
function F(){};
F.prototype = o;
var object = new F();
object.sayHi = function(){
console.log("hi!");
}
return object;
}
ECMAScript提供了一个方法 Object.create() 来实现这种原型模式继承。接受两个参数:作为新对象原型的对象和(可选的)一个为新对象定义额外属性的对象,第二个参数和Object.defineProperties()方法的第二个参数相同。
var person = {
name: "Tom",
friends:["Shelby","Court","Van"]
}
var p1 = Object.create(person,{
name:{value : "Greg"}
});
p1.name = "Greg";
p1.friends.push("Rob");
console.log(p1.name); //Greg
var p2 = Object.create(person);
p2.name = "Linda";
p2.friends.push("Barbie");
console.log(person.friends); // ["Shelby", "Court", "Van", "Rob", "Barbie"]
2.4 原型式的组合继承
上述提到的构造函数和原型的组合继承因为在创建新子类对象实例时,会执行两次超类构造函数(一次是给子类构造函数原型赋值,一次是执行 new SubType() ),这导致子类对象实例和它的原型都有一套超类构造函数的属性。
可以减少一次:只要给子类原型指定为超类原型对象,而不必为了指定子类的原型而调用超类的构造函数。
function SuperType(name){
this.name= name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name,age){
SuperType.call(this,name);
this.age = age;
}
function inheritPrototype(subType,superType){
function F(){};
F.prototype = superType.prototype;
subType.prototype = new F(); // 子类的原型继承了超类的原型对象
subType.prototype.constructor = subType;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function (){
console.log(this.age);
}var instance1 = new SubType("tom",29);
instance1.colors.push("black");
console.log(instance1.colors); // ["red", "blue", "green", "black"]
instance1.sayName(); // tom
instance1.sayAge(); //
var instance2 = new SubType("jack",32);
console.log(instance2.colors); // ["red", "blue", "green"]
instance2.sayName(); //jack
instance2.sayAge(); //
js 中的原型链与继承的更多相关文章
- JavaScript中的原型链和继承
理解原型链 在 JavaScript 的世界中,函数是一等公民. 上面这句话在很多地方都看到过.用我自己的话来理解就是:函数既当爹又当妈."当爹"是因为我们用函数去处理各种&quo ...
- 理解js中的原型链
对象有”prototype”属性,函数对象有”prototype”属性,原型对象有”constructor”属性. 关于原型 在JavaScript中,原型也是一个对象,通过原型可以实现对象的属性继承 ...
- JS中注意原型链的“指向”
昨天压缩Js文件时发现了项目中的一个prototype的问题代码如下所示: 1. <script> var XXX = function(){ }; var x1 = new XXX(); ...
- JS中的原型链和原型的认识
这篇文章主要是学习一下JavaScript中的难点------原型和原型链 自定义一个对象 我们学习一门编程语言,必然要使用它完成一些特定的功能,而面向对象的语言因为符合人类的认知规律,在这方面做得很 ...
- 理解js中的原型链,prototype与__proto__的关系
说到prototype,就不得不先说下new的过程. 我们先看看这样一段代码: 1 <script type="text/javascript"> 2 var Pers ...
- 【转】理解js中的原型链,prototype与__proto__的关系
说到prototype,就不得不先说下new的过程. 我们先看看这样一段代码: 1 <script type="text/javascript"> 2 var Pers ...
- 关于js中的原型链的理解
我们知道无论什么时候只要创建了一个函数,就会为该函数创建一个prototype属性,这个属性指向函数的原型对象,默认情况下所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包 ...
- [转]理解js中的原型链,prototype与__proto__的关系
本文转自:http://rockyuse.iteye.com/blog/1426510 说到prototype,就不得不先说下new的过程. 我们先看看这样一段代码: 1 <script typ ...
- 小谈js原型链和继承
原型(prototype)在js中可是担当着举足轻重的作用,原型的实现则是在原型链的基础上,理解原型链的原理后,对原型的使用会更加自如,也能体会到js语言的魅力. 本文章会涉及的内容 原型及原型对象 ...
随机推荐
- Docker的安装和启动
2.Docker安装与启动 2.1安装环境说明 Docker官方建议在Ubuntu中安装,因为Docker是基于Ubuntu发布的,而且一般Docker出现的问题Ubuntu是最先更新或者打补丁的.在 ...
- Mybatis五(一级二级缓存、第三方缓存)
一级缓存 Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存只是相对于同一个SqlSession而言.所以在参数和SQL完全一样的情况下,我们使用同一个SqlSess ...
- kettle实现简单的增量同步
下载 pdi-ce-7.0.0.0-25.zip 解压 安装jdk 1.7以上的版本 配置环境变量 下载并将mysql-connector-java-5.1.39.jar 拷贝到 \data-inte ...
- NDK samples以及部分博客
谷歌的ndk samples Android NDK samples with Android Studio http://developer.android.com/ndk 引用C/C++文件请参考 ...
- 廖雪峰老师Python3教程练习整理
1.定义一个函数quadratic(a, b, c),接收3个参数,返回一元二次方程:ax2 + bx + c = 0的两个解 # -*- coding: utf-8 -*-import mathde ...
- django之relacted.py(探秘django的关联field)
生成model类对象时,传入的每个field对象都会调用其contribute_to_class函数,生成对应的属性. def contribute_to_class(self, cls, name, ...
- 20165304实验一java开发环境熟悉
实验报告封面 一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:李松杨 学号:20165304 指导教师:娄嘉鹏 实验日期:2018年4月2日 实验时间:13:45 - 15:25 实 ...
- 机器学习进阶-图像形态学操作-开运算与闭运算 1.cv2.morphologyEx(进行各类形态学变化) 2.op=cv2.MORPH_OPEN(先腐蚀后膨胀) 3.op=cv2.MORPH_CLOSE(先膨胀后腐蚀)
1.cv2.morphologyEx(src, op, kernel) 进行各类形态学的变化 参数说明:src传入的图片,op进行变化的方式, kernel表示方框的大小 2.op = cv2.MO ...
- Dubbo的优化 --- 开发时使用
开发时的三个优化: 1.开发者在本地开发的时候启动Dubbo比较麻烦,所以采用直接连接的配置: 2.开发者本地开发时会打断点调试,会超过Dubbo默认的超时时间1s,所以需要全局设置超时时间: 3.开 ...
- easy.py使用中ValueError: could not convert string to float: svm_options错误问题解决
在使用easy.py中出现如下图所示问题 解决方法: 1.找到cmd = '{0} -svmtrain "{1}" -gnuplot "{2}" "{ ...