JS对象继承与原型链
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对象继承与原型链的更多相关文章
- 一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)
上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承. 一.原型链继承 1.通过设置prototype指向“父类”的实例来实现继承. function Obj1() { this.name1 ...
- JS面向对象(2) -- this的使用,对象之间的赋值,for...in语句,delete使用,成员方法,json对象的使用,prototype的使用,原型继承与原型链
相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...
- JS function 是函数也是对象, 浅谈原型链
JS function 是函数也是对象, 浅谈原型链 JS 唯一支持的继承方式是通过原型链继承, 理解好原型链非常重要, 我记录下我的理解 1. 前言 new 出来的实例有 _proto_ 属性, 并 ...
- js继承之原型链方式实现
温故而知新: 在之前的文章已经重点了解了原型对象,今天就理一理这个原型对象在原型链式的继承中的使用 function a(x,y){this.x=x;this.y=y;} //定义一个函数,当构造函数 ...
- JS对象继承篇
JS对象继承篇 ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的 原型链 其基本思路是利用原型让一个引用类型继承另一个引用类型的属性和方法 function Person() ...
- (翻译) Inheritance and the prototype chain 继承和原型链
JavaScript is a bit confusing for developers experienced in class-based languages (like Java or C++) ...
- JavaScript之继承(原型链)
JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...
- 一篇JavaScript技术栈带你了解继承和原型链
作者 | Jeskson 来源 | 达达前端小酒馆 1 在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则. 那么 ...
- 关于JavaScript的原型继承与原型链
在讨论原型继承之前,先回顾一下关于创建自定义类型的方式,这里推荐将构造函数和原型模式组合使用,通过构造函数来定义实例自己的属性,再通过原型来定义公共的方法和属性. 这样一来,每个实例都有自己的实例属性 ...
随机推荐
- 小A点菜 水题 dp 背包
基本上还是01背包,首先注意必须正好花光钱,所以初始化时除了dp[0]以外其他都要设置成inf,然后因为求方案数,所以基本方程为dp[i] = dp[i-x] + dp[i],再根据inf进行一些特殊 ...
- Redit集群搭建-Sentinel模式搭建
Redit集群搭建 学习了: Windows:http://blog.csdn.net/mrxiagc/article/details/52799081 Linux:https://www.cnblo ...
- JNI之——'cl' 不是内部或外部命令,也不是可执行的程序或批处理文件
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46604315 问题的出现: 今天卸载了VS2010,重装vs2008后.发 ...
- PIC18F4520 + NRF24L01
SI SO应该对调过来用.. TX /* ** Tx.c ** Transmit test program for PIC18F4520 and nRF24L01 or nRF24L01+ ** Us ...
- nyoj--42--一笔画问题(并查集)
一笔画问题 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 zyc从小就比较喜欢玩一些小游戏,其中就包括画一笔画,他想请你帮他写一个程序,判断一个图是否能够用一笔画下来. ...
- nyoj--49--开心的小明(背包)
开心的小明 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 小明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他 ...
- django 笔记11 装饰器
在views.py创建 一般用来cookies的装饰器 def auth(func): def inner(request, *args, **kwargs): v = request.COOKIES ...
- MySql创建指定字符集的数据库
以创建字符集为utf8的数据库为例: CREATE DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; CREAT ...
- POJ 3277 线段树+扫描线
题意: 思路: 线段树求矩形面积的并...同 POJ 1151 //By SiriusRen #include <cstdio> #include <algorithm> us ...
- DC、CDC及CDC的各个子类
设备描述表是一个包含设备信息的结构体(物理设备如显示器.打印机),MFC中关于图像操作都需要DC来完成.HDC是Windows的一种数据类型,是设备描述句柄:CDC是MFC封装的Windows 设 ...