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的原型继承与原型链
在讨论原型继承之前,先回顾一下关于创建自定义类型的方式,这里推荐将构造函数和原型模式组合使用,通过构造函数来定义实例自己的属性,再通过原型来定义公共的方法和属性. 这样一来,每个实例都有自己的实例属性 ...
随机推荐
- exadata(硬件更换文档部分)
Maintaining Flash Disks Replacing a Flash Disk Due to Flash Disk Failure Each Exadata Storage Server ...
- POJ 3254 Corn Fields 状态压缩DP (C++/Java)
id=3254">http://poj.org/problem? id=3254 题目大意: 一个农民有n行m列的地方,每一个格子用1代表能够种草地,而0不能够.放牛仅仅能在有草地的. ...
- iOS - 自己定义alertView,继承自UIView,能够加入子视图,标题图片+文字
这个更简单,能够看下demo https://github.com/DYLAN-LWB/WBAlertView 自己定义alertView,继承自UIView,能够在消息区域加入子视图:a ...
- 巧妇能为少米之炊(1)——Android下小内存下的生存之道
常常听到身边用安卓的朋友抱怨手机卡顿,内存动不动就快没了.而Google声称在512M的内存下也能流畅执行Android 4.4.究竟它做了什么? 总结一下它主要做了四件事: 1.优化内核,使用Act ...
- thinkphp5项目--个人博客(五)
thinkphp5项目--个人博客(五) 项目地址 fry404006308/personalBlog: personalBloghttps://github.com/fry404006308/per ...
- spark rdd saveAsTextFile保存为文件
sc.parallelize(["one", "two", "two", "three", "three&qu ...
- 3.c语言结构体成员内存对齐详解
一.关键一点 最关键的一点:结构体在内存中是一个矩形,而不是一个不规则形状 二.编程实战 #include <stdlib.h> #include <stdio.h> stru ...
- 1355: [Baltic2009]Radio Transmission
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 958 Solved: 659[Submit][Status][Discuss] Description ...
- The IDL compiler
The IDL compiler or bindings generator transcompiles Web IDL to C++ code, specifically bindings betw ...
- 一个icon的选中与不选中
页面的样式展示 1.页面中选中的状态 2.页面中未选中的状态 3.俩个icon代表的状态 页面的布局展示 <label> <i class="iconfont icon-d ...