1.以复制方式实现的继承

1.1浅拷贝

基本类型的复制

 var parent = {
lanage: "chinese"
} var child = {
name: "xxx",
age: 12
} function extend(parent, child) {
var child = child || {};
for (const propertype in parent) {
child[propertype] = parent[propertype];
}
} extend(parent, child); console.log(child);//{ name: 'xxx', age: 12, lanage: 'chinese' }

以上代码中,通过一个extend()函数,将父对象parent的属性遍历赋给子对象child,从而实现继承。

但是这种字面量复制的方式存在巨大的缺陷,当父对象有引用类型的属性时,通过这么复制的方式,就像上一节中的var b = a一样,只会将a对象的引用赋给b对象,结果两者是指向同一个对象内存的,继承出来的子对象的属性是同一个,显然是不能满足需求的,(基本类型之间画等号是值的复制,引用类型之间画等号是引用的复制)所以就需要另谋出路。

1.2.深拷贝

利用递归加类型判断复制引用类型

 var parent = {
lanage: "chinese",
address: {
home: "gansu",
office: "xian"
},
schools: ["xiaoxue", "zhongxue", "daxue"]
} var child = {
name: "xxx",
age: 12
} function extendDeeply(parent, child) {
var child = child || {};
for (const propertype in parent) {
//首先判断父对象的当前属性是不是引用类型
if (typeof parent[propertype] === "object") {
//再判断该引用类型是不是数组,是则给子对象初始化为空数组,否则初始化为空对象
child[propertype] = Array.isArray(parent[propertype]) ? [] : {};
//递归调用自己,将父对象的属性复制到子对象
extendDeeply(parent[propertype], child[propertype]);
} else {
//基本类型直接复制
child[propertype] = parent[propertype];
}
}
} extendDeeply(parent, child);
console.log(child);
child.schools[0] = "qinghua"; //改变子对象的属性值
child.address.home = "tianjin"; console.log(child.schools[0]); //qinghua
console.log(parent.schools[0]); //xiaoxue
console.log(child.address.home); //tianjin
console.log(parent.address.home); //gansu

可见此时子对象的改变并不会影响到父对象,父子彻底决裂。这便是深拷贝实现的继承。

注意:for in 是可以遍历数组的,结果为数组元素下标。

2.以构造函数实现继承

 function Parent() {
this.name = "name";
this.age = 12;
} function Child() {
Parent.call(this);
this.language = "chinese";
} var child = new Child();
console.log(child);//{ name: 'name', age: 12, language: 'chinese' }
child.name = "swk";
console.log(new Parent().name);//name

如上所示,通过在子类构造函数中调用父类构造函数,将父类属性继承到子类对象上,new出来的每一个子类对象都是独立的实例,这种方式更符合面向对象的思想。

3.以原型方式实现继承

 var person = {name: "pname"};

 function myCreate(person) {
var ins;
function F() { };
F.prototype = person;
ins = new F();
return ins;
} var c = new myCreate(person);
console.log(c.name); //pname
console.log(c); //{}

如上所示,将一个构造函数的原型替换为父对象,然后返回该构造函数的实例,如此一来创建的子对象就是F的实例,并且其原型为父对象,所以c.name可以被查找到,但子对象c本身是没有属性的。这种直接重写prototype原型对象的弊端在于会断掉原本的原型链,即没有了继承自Object的方法,和给原型对象prototype上添加属性是不同的。

4.JS原型链

盗一波大神的经典图

从该图可以看出两点

4.1从原型prototype层面:

  • 不论是 new Foo()自定义构造函数,new Object()系统构造函数,还是对象字面量创建出来的对象,只要是对象,其原型最终都指向Object.prototype对象,自定义的多绕了一步,就像Java里说的,Object.prototype是一切JS对象的根对象。
  • 函数的原型都指向Function.prototype,而在JS中,函数也是对象的一种,所以符合第一条。

4.2从构造器constructor层面

  • 首先对象的构造器肯定是指向他的构造函数,f1, f2指向Foo(), o1, o2指向Object()。
  • 而构造函数Foo()和Object()的constructor属性最终指向函数构造器Function()。

JS对象继承与原型链的更多相关文章

  1. 一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)

    上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承. 一.原型链继承 1.通过设置prototype指向“父类”的实例来实现继承. function Obj1() { this.name1 ...

  2. JS面向对象(2) -- this的使用,对象之间的赋值,for...in语句,delete使用,成员方法,json对象的使用,prototype的使用,原型继承与原型链

    相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...

  3. JS function 是函数也是对象, 浅谈原型链

    JS function 是函数也是对象, 浅谈原型链 JS 唯一支持的继承方式是通过原型链继承, 理解好原型链非常重要, 我记录下我的理解 1. 前言 new 出来的实例有 _proto_ 属性, 并 ...

  4. js继承之原型链方式实现

    温故而知新: 在之前的文章已经重点了解了原型对象,今天就理一理这个原型对象在原型链式的继承中的使用 function a(x,y){this.x=x;this.y=y;} //定义一个函数,当构造函数 ...

  5. JS对象继承篇

    JS对象继承篇 ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的 原型链 其基本思路是利用原型让一个引用类型继承另一个引用类型的属性和方法 function Person() ...

  6. (翻译) Inheritance and the prototype chain 继承和原型链

    JavaScript is a bit confusing for developers experienced in class-based languages (like Java or C++) ...

  7. JavaScript之继承(原型链)

    JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...

  8. 一篇JavaScript技术栈带你了解继承和原型链

    作者 | Jeskson 来源 | 达达前端小酒馆 1 在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则. 那么 ...

  9. 关于JavaScript的原型继承与原型链

    在讨论原型继承之前,先回顾一下关于创建自定义类型的方式,这里推荐将构造函数和原型模式组合使用,通过构造函数来定义实例自己的属性,再通过原型来定义公共的方法和属性. 这样一来,每个实例都有自己的实例属性 ...

随机推荐

  1. Caused by: java.lang.ClassNotFoundException: com.njupt.libgdxbase.MainActivity

    在使用libgdx来开发游戏时.假设遇到这样的问题.非常可能是由于你没有在libgdx的项目中导入Android的现骨干jar包导致的. 解决方法例如以下: 右击项目---"build pa ...

  2. UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集

    UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集 ACM 题目地址:option=com_onlinejudge&Itemid=8&page=sh ...

  3. Angry IP Scanner 获取设备的IP

    给大家介绍一款软件Angry IP scanner,这款软件最大的用处就是能够扫描某一网段的各个主机的ip.通过使用发现,原理就是通过高速的ping每一个ip,假设有主机存在.就获取这个主机的user ...

  4. 怎样实如今Windows下编写的代码,直接在Linux下编译

    方法一: 怎样实如今Windows7下编写Linux程序.写完程序以后.不用复制文件,直接在Linux(RHEL6.5)机器上编译最新的代码. 1.首先将Windows的代码目录设置为共享目录: 2. ...

  5. Android微信智能心跳方案 Android微信智能心跳方案

    原文地址: http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=207243549&idx=1&sn=4ebe4beb81 ...

  6. poj_3667线段树区间合并

    对照着notonlysuccess大牛的代码写的 #include<iostream> #include<cstdio> #include<cstring> #in ...

  7. 曲根英语万词---二、evoke

    曲根英语万词---二.evoke 一.总结 一句话总结:evoke v.唤起,引起 词根:-voc-, -vok- [词根含义]:声音,叫喊 1.consecrate? v,供奉,奉为神圣 -ate, ...

  8. zzulioj--1778-- 和尚特烦恼4——有多少战斗力(gcd)

    1778: 和尚特烦恼4--有多少战斗力 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 259  Solved: 123 SubmitStatusWe ...

  9. 手把手教你进行R语言的安装及安装过程中相关问题解决方案

    这篇文章旨在为R语言的新手铺砖引路,行文相对基础,希望对在R语言安装上有问题的小伙伴提供帮助和指引.一.什么是 R 语言R 编程语言被广泛应用在统计科学和商业领域. 在各种编程语言排名中 R 语言的排 ...

  10. [BeiJing2009 WinterCamp]取石子游戏 Nim SG 函数

    Code: #include<cstdio> #include<algorithm> #include<cstring> using namespace std; ...