上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承。

一、原型链继承

1.通过设置prototype指向“父类”的实例来实现继承。

function Obj1() {
this.name1 = "张三";
}
function Obj2() {
}
Obj2.prototype = new Obj1();
var t2 = new Obj2();
alert(t2.name1);

这里有个明显的缺点就是:(如果父类的属性是引用类型,那么我们在对象实例修改属性的时候会把原型中的属性修改,这样会在每个实例对象中改变数据,而这不是我们想要的效果)

function Obj1() {
this.arr = ["张三"];
}
function Obj2() {
}
Obj2.prototype = new Obj1();
var t2 = new Obj2();
alert(t2.arr);//打印“张三”
t2.arr[t2.arr.length] = "李四";
var t1 = new Obj2();
alert(t1.arr);//打印“张三,李四”

例:

function Obj1() {
this.arr = ["张三"];
}
function Obj2() {
}
Obj2.prototype = new Obj1();
var t2 = new Obj2();
alert(t2.arr);//打印“张三”
t2.arr[t2.arr.length] = "李四";
var t1 = new Obj2();
alert(t1.arr);//打印“张三,李四”

那我们怎样规避这种问题呢?接着往下看。

2. 利用构造函数来实现继承

function Obj1() {
this.arr = ["张三"];
}
function Obj2() {
Obj1.call(this);//【1.新增】
}
//Obj2.prototype = new Obj1();【2.注释这行】
var t2 = new Obj2();
alert(t2.arr);//打印“张三”
t2.arr[t2.arr.length] = "李四";
var t1 = new Obj2();
alert(t1.arr);//打印“张三,李四”

我们看到上面代码,就注释了一行,新增了以后。打印出来的效果完全不一样了。现在的arr属性是每个实例对象独有的了。(之前是定义到原型上的,而原型的属性对每个实例都是共享的)

例:

function Obj1() {
this.arr = ["张三"];
}
function Obj2() {
Obj1.call(this);//【1.新增】
}
//Obj2.prototype = new Obj1();【2.注释这行】
var t2 = new Obj2();
alert(t2.arr);//打印“张三”
t2.arr[t2.arr.length] = "李四";
var t1 = new Obj2();
alert(t1.arr);//打印“张三,李四”

同样,单纯的这种方式也是有问题的。因为我们这样就无法继承对象的方法了。如:

function Obj1() {
this.arr = ["张三"];
}
Obj1.prototype.sayHi = function () { alert(this.arr); }////【1.新增】
function Obj2() {
Obj1.call(this);
}
var t2 = new Obj2();
//t2里面是没有sayHi方法的

我们可以使用原型和构造的混用来解决,如下:

3.通过原型和构造来实现继承

function Obj1() {
this.arr = ["张三"];
}
Obj1.prototype.sayHi = function () { alert(this.arr); }
function Obj2() {
Obj1.call(this);
}
Obj2.prototype = new Obj1();//【1.新增】
var t2 = new Obj2();
t2.sayHi();

如上,通过构造函数中的  Obj1.call(this); 和设置原型属性 Obj2.prototype = new Obj1(); 结合使用,完美解决问题。

这里需要注意一个地方,如果把 Obj2.prototype = new Obj1(); 改成 Obj2.prototype = Obj1.prototype ; 的话,会有你想不到的问题。如:

function Obj1() {
this.arr = ["张三"];
}
Obj1.prototype.sayHi = function () { alert(this.arr); }
function Obj2() {
Obj1.call(this);
}
Obj2.prototype = Obj1.prototype;//【1.新增】
var t2 = new Obj2();
t2.constructor.prototype.sayHi = function () { alert("test") };//修改Obj2中的原型的方法
var t1 = new Obj1();
t1.sayHi();
//影响到了Obj1中的原型的方法。因为 Obj2.prototype = Obj1.prototype;让两个对象的原型指向了同一处。
//所以还是只能用Obj2.prototype = new Obj1();

例:

function Obj1() {
this.arr = ["张三"];
}
Obj1.prototype.sayHi = function () { alert(this.arr); }
function Obj2() {
Obj1.call(this);
}
Obj2.prototype = Obj1.prototype;//【1.新增】
var t2 = new Obj2();
t2.constructor.prototype.sayHi = function () { alert("test") };//修改Obj2中的原型的方法
var t1 = new Obj1();
t1.sayHi();

4.什么是原型链

如:

//*************Obj1****
function Obj1() {
this.arr = ["张三"];
}
Obj1.prototype.sayHi = function () { alert(this.arr); } //*************Obj2****
function Obj2() {
Obj1.call(this);
this.name = "张三";
}
Obj2.prototype = new Obj1();
Obj2.prototype.sayHi2 = function () { alert(this.name); }; //*************Obj3****
function Obj3() {
Obj2.call(this);
}
Obj3.prototype = new Obj2();
Obj3.prototype.sayHi3 = function () { }; //*******************
var t3 = new Obj3();
t3.sayHi();

Obj3继承Obj2,Obj2继承Obj1。我们的Obj3的实例对象访问sayHi的时候,会先去Obj3的实例对象中找sayHi方法(没找到),然后去Obj3的原型中找(没找到),然后去父类Obj2的原型中找(没找到),然后去Obj1的原型中找(找到了)。这个找的路径就是原型链。


(补充分割线20151230)

以上,我们在说继承的时候,我们都是 obj2.prototype = new obj1(); 原型指向父类构造函数。其实这样有一个问题。如:

function obj1() {
this.name2 = "张三";
}
obj1.prototype.sayhi = function () {
alert(this.name2);
} function obj2() {
obj1.call(this);//继承属性
}
obj2.prototype = new obj1();
var obj = new obj2();

我们看到name2这个属性,并不是我们想要在prototype中的prototype.name2中继承过来的。(感觉不是那么干净)

然而,我们可以:

function obj1() {
this.name2 = "张三";
}
obj1.prototype.sayhi = function () {
alert(this.name2);
} function obj2() {
obj1.call(this);//继承属性
}
//obj2.prototype = new obj1();
obj2.prototype = Object.create(obj1.prototype);//继承原型中的方法【E5中才有的一种新的对象创建方式】
var obj = new obj2();

这是学习记录,不是教程。文中错误难免,您可以指出错误,但请不要言辞刻薄。

原文链接:http://haojima.net/zhaopei/517.html

本文已同步至目录索引:一步步学习javascript

欢迎上海“程序猿/媛”、"攻城狮"入群:【沪猿】229082941 入群须知

欢迎对个人博客感兴趣的道友加入群:【嗨-博客】469075305 入群须知

如果您觉得文章对您有那么一点点帮助,那么麻烦您轻轻的点个赞,以资鼓励。

一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)的更多相关文章

  1. 一步步学习javascript基础篇(0):开篇索引

    索引: 一步步学习javascript基础篇(1):基本概念 一步步学习javascript基础篇(2):作用域和作用域链 一步步学习javascript基础篇(3):Object.Function等 ...

  2. 一步步学习javascript基础篇(3):Object、Function等引用类型

    我们在<一步步学习javascript基础篇(1):基本概念>中简单的介绍了五种基本数据类型Undefined.Null.Boolean.Number和String.今天我们主要介绍下复杂 ...

  3. 一步步学习javascript基础篇(4):面向对象设计之创建对象(工厂、原型和构造函数等模式)

    前面我们介绍了可以通过Object构造函数或对象字面量都可以用来创建单个对象,但是如果需要创建多个对象的话,显然很多冗余代码. 接下来介绍几种模式来创建对象.不过在此之前,我们还是先来了解下 type ...

  4. 一步步学习javascript基础篇(8):细说事件

    终于学到事件了,不知道为何听到“事件”就有一种莫名的兴奋.可能是之前的那些知识点过于枯燥无味吧,说起事件感觉顿时高大上了.今天我们就来好好分析下这个高大上的东西. 可以说,如果没有事件我们的页面就只能 ...

  5. 一步步学习javascript基础篇(1):基本概念

    一.数据类型 数据类型 基本数据类型(五种) Undefined Null Boolean Number String 复杂数据类型(一种) Object Undefined:只有一个值undefin ...

  6. 一步步学习javascript基础篇(7):BOM和DOM

    一.什么是BOM.什么是DOM BOM即浏览器对象模型,主要用了访问一些和网页无关的浏览器功能.如:window.location.navigator.screen.history等对象. DOM即文 ...

  7. 一步步学习javascript基础篇(6):函数表达式之【闭包】

    回顾前面介绍过的三种定义函数方式 1. function sum (num1, num2) { return num1 + num2; }  //函数声明语法定义 2. var sum = funct ...

  8. 一步步学习javascript基础篇(2):作用域和作用域链

    作用域和作用域链 js的语法用法非常的灵活,且稍不注意就踩坑.这集来分析下作用域和作用域链.我们且从几道题目入手,您可以试着在心里猜想着答案. 问题一. if (true) { var str = & ...

  9. 一步步学习javascript基础篇(9):ajax请求的回退

    需求1: ajax异步请求 url标识请求参数(也就是说复制url在新页面打开也会是ajax后的效果) ajax异步请求没问题,问题一般出在刷新url后请求的数据没了,这就是因为url没有记录参数.如 ...

随机推荐

  1. 网站跨站点脚本,Sql注入等攻击的处理

    从360安全论坛里找到的一段代码,经过整理封装,直接在站点Global.asax文件或写一个HttpModule来拦截恶意请求即可: http://bbs.webscan.360.cn/forum.p ...

  2. ECMAScript 5

    2009年12月,ECMAScript 5.02011年6月,ECMAscript 5.1版发布2015年6月,ECMAScript 6正式通过,成为国际标准ES6第一个版本 ES2015,发布于20 ...

  3. JAVA中MAP值保持顺序不变

    今天在进行JAVA开发过程中,因需要使用MAP来存放数据,同时希望MAP中KEY的顺序与放入顺序保持一致. 在使用HashMap之后,发现KEY的顺序是乱序的,每次打印还不太一样.上网查询资料之后发现 ...

  4. tomcat热部署

    tomcat默认支持热部署,修改文件会自动加载部署,不需要重启容器 server.xml配置如下所示 autoDeploy=”true” — 自动部署 reloadable=”true” — 自动加载

  5. OpenCv遍历图像小结

    参考:http://www.cnblogs.com/ronny/p/opencv_road_2.html http://blog.csdn.net/xiaowei_cqu/article/detail ...

  6. Building a RESTful Web Service

    Reference: https://spring.io/guides/gs/rest-service/ 参照上述链接进行操作,使用gradle build. 因为total new to this. ...

  7. CentOS 6.5 Nginx 配置

    1.安装所有 http功能: ./configure --user=www-data --group=www-data --with-http_ssl_module --with-http_reali ...

  8. 【专业找水题】状压dp最水题,没有之一

    题目链接 现在代码能力没上升,倒是越来越会找水题了(比例题还水的裸题你值得拥有) 这网站不是针对竞赛的,所以时空限制都很宽松 然后就让我水过去了 对于每个点,包括自己的前m个元素是否取都是一种状态,所 ...

  9. 初步了解CPU

    了解CPU By JackKing_defier 首先说明一下,本文内容主要是简单说明CPU的大致原理,所需要的前提知识我会提出,但是由于篇幅我不会再详细讲解需要的其他基础知识.默认学过工科基础课. ...

  10. mas_makeConstraints && mas_remakeConstraints && mas_updateConstraints 用法与注意事项

    mas_makeConstraints && mas_remakeConstraints && mas_updateConstraints 用法与注意事项 字数400 ...