JS中5种经典继承方式
继承
JS中继承的概念:
- 通过【某种方式】让一个对象可以访问到另一个对象中的属性和方法,我们把这种方式称之为继承
并不是所谓的xxx extends yyy
为什么要使用继承?
- 有些对象会有方法(动作、行为),而这些方法都是函数,如果把这些方法和函数都放在构造函数中声明就会导致内存的浪费
function Person(){
this.say=function(){
console.log("你好")
}
}
var p1=new Person();
var p2=new Person();
console.log(p1.say === p2.say); //false
继承的第一种方式:原型链继承1
Person.prototype.say=function(){
console.log("你好")
}
- 缺点:添加1、2个方法无所谓,但是如果方法很多会导致过多的代码冗余
继承的第二种方式:原型链继承2
Person.prototype = {
//切记不能忘记
constructor:Person,
say:function(){
console.log("你好");
},
run:function(){
console.log("正在进行百米冲刺");
}
}
- 注意点:
- a、一般情况下,应该先改变原型对象,再创建对象
- b、一般情况下,对于新原型,会添加一个constructor属性,从而不破坏原有的原型对象的结构
继承的第三种方式:拷贝继承(混入继承:mixin)
- 场景:有时候想使用某个对象中的属性,但是又不能直接修改它,于是就可以创建一个该对象的拷贝
- 实际运用:
- jquery:$.extend:编写jquery插件的必经之路
- 基于jquery封装一个表格控件
- jquery:$.extend:编写jquery插件的必经之路
var o1={ age:2 };
var o2 = o1;
o2.age=18;
//1、修改了o2对象的age属性
//2、由于o2对象跟o1对象是同一个对象
//3、所以此时o1对象的age属性也被修改了
var o3={gender:"男",grade:"初三",group:"第五组",name:"张三"};
var o4={gender:"男",grade:"初三",group:"第五组",name:"李四"};
//上述代码中,如果使用拷贝继承对代码进行优化会非常和谐
//实现拷贝继承:
//1、已经拥有了o3对象
//2、创建一个o3对象的拷贝(克隆):for...in循环
//3、修改克隆对象,把该对象的name属性改为"李四"
- 实现1:
var source={name:"李白",age:15}
var target={};
target.name=source.name
target.age=source.age;
浅拷贝和深拷贝
- 浅拷贝只是拷贝一层属性,没有内部对象
- 深拷贝其实是利用了递归的原理,将对象的若干层属性拷贝出来
var students=[
{name:"",age:""},
{name:"",age:""}
]
上面的方式很明显无法重用,实际代码编写过程中,很多时候都会使用拷贝继承的方式,所以为了重用,可以编写一个函数把他们封装起来:
function extend(target,source){
for(key in source){
target[key]=source[key];
}
return target;
}
extend(target,source)
由于拷贝继承在实际开发中使用场景非常多,所以很多库都对此有了实现
- jquery:$.extend
es6中有了 <对象扩展运算符> 仿佛就是专门为了拷贝继承而生:
- 优点:简单的令人发指
var source={name:"李白",age:15}
//让target是一个新对象,同时拥有了name、age属性
var target={ ...source }
var target2={ ...source,age:18 }
继承的第四种方式:原型式继承:(道格拉斯在蝴蝶书中提出来的)
- 场景:
- a、创建一个纯洁的对象:对象什么属性都没有
- b、创建一个继承自某个父对象的子对象
var parent={ age:18,gender:"男"};
var student=Object.create(parent);
//student.__proto__===parent
- 使用方式:
- 空对象:Object.create(null)
var o1={ say:function(){} }
var o2=Object.create(o1);
继承的第五种方式:借用构造函数实现继承
- 场景:适用于2种构造函数之间逻辑有相似的情况
- 原理:函数的call、apply调用方式
function Animal(name,age,gender){
this.name=name;
this.age=age;
this.gender=gender;
}
function Person(name,age,gender,say){
this.name=name;
this.age=age;
this.gender=gender;
this.say=function(){
}
}
局限性:Animal(父类构造函数)的代码必须完全适用于Person(子类构造函数)
以上代码用借用构造函数实现
function Animal(name,age){
this.name=name;
this.age=age;
}
function Person(name,age,address){
Animal.call(this,name);
//this.name=name;
//this.age=age;
this.address=address;
}
- 寄生继承、寄生组合继承...
JS中5种经典继承方式的更多相关文章
- JS中三种字符串连接方式及其性能比较
工作中经常会碰到要把2个或多个字符串连接成一个字符串的问题,在JS中处理这类问题一般有三种方法,这里将它们一一列出顺便也对它们的性能做个具体的比较. 第一种方法 用连接符“+”把要连接的字符串连起来 ...
- 详解js中的寄生组合式继承
寄生组合式继承是js中最理想的继承方式, 最大限度的节省了内存空间. js中的寄生组合式继承要求是: 1.子对象有父对象属性的副本, 且这些不应该保存在子对象的prototype上. 2. ...
- js中的原型、继承的一些想法
最近看到一个别人写的js类库,突然对js中的原型及继承产生了一些想法,之前也看过其中的一些内容,但是总不是很清晰,这几天利用空闲时间,对这块理解了一下,感觉还是有不通之处,思路上没那么条理,仅作为分享 ...
- [转]js中几种实用的跨域方法原理详解
转自:js中几种实用的跨域方法原理详解 - 无双 - 博客园 // // 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同 ...
- 关于js中两种定时器的设置及清除(转载)
1.JS中的定时器有两种: window.setTimeout([function],[interval]) 设置一个定时器,并且设定了一个等待的时间[interval],当到达时间后,执行对应的方法 ...
- mybatis中两种取值方式?谈谈Spring框架理解?
1.mybatis中两种取值方式? 回答:Mybatis中取值方式有几种?各自区别是什么? Mybatis取值方式就是说在Mapper文件中获取service传过来的值的方法,总共有两种方式,通过 $ ...
- js中三种定义变量 const, var, let 的区别
js中三种定义变量的方式const, var, let的区别 1.const定义的变量不可以修改,而且必须初始化. 1 const b = 2;//正确 2 // const b;//错误,必须初始化 ...
- JS中几种常见的数组算法(前端面试必看)
JS中几种常见的数组算法 1.将稀疏数组变成不稀疏数组 /** * 稀疏数组 变为 不稀疏数组 * @params array arr 稀疏数组 * @return array 不稀疏的数组 */ f ...
- [js]js中4种无节操的预解释情况
js中4种无节操的预解释情况 - 1. if语句即使条件不成立,条件里的表达式也会进行预解释. - 2. 匿名函数的预解释: 只对等号左边与解释 - 3. 自执行函数的预解释: 不进行预就解释, 执行 ...
随机推荐
- Security+ 认证考过经验分享 802分飘过
PART 1/考前准备 1.针对与新人.学生建议看每一节直播课程,老师会结合自己的工作工作经验讲解课程,可以帮助学生理解知识. 2.备考期间建议官方指导手册至少看两遍以上,我在结合自己的做题库时发现有 ...
- 把xml数据直接插入到sqlserver数据库
存储过程: ALTER proc [ali].[ins_冻结金额表] @xmldoc varchar(max), ) as declare @idoc int exec sp_xml_prepared ...
- linux下安装kubectl
查看所有版本: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md 下载指定版本: curl -O https://dl ...
- python3 练手实例1 计算三角形周长和面积
def j(): a,b,c=map(float,input('请输入三角形三条边的长度,用空格隔开:').split()) if a>0 and b>0 and c>0 and a ...
- 【翻译】 Guice 动机——依赖注入的动机
原文链接 动机 将所有的内容连接在一起时应用开发的一个单调乏味的部分.有几种方式来将数据.服务.presetntation类连接到一起.为了对比这些方法,我将为披萨订购网站编写账单代码: public ...
- 微信小程序常见的坑
wxml的标签跟html里面的一些标签是一样的,比如view标签相当于div标签,text标签相当于span标签. 在微信小程序中,表单元素都是原生组件,微信小程序中原生组件层级最高,所以在用inpu ...
- css 实现加载中3个点跳动
<style type="text/css">.loading:after { overflow: hidden; display: inline-block; ver ...
- sql选择
关系型数据库遵循ACID规则 1.A (Atomicity) 原子性 原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整 ...
- BH1750FVI调试
在写此博客之前已经看了几遍数据手册了,现在已经调试成功了,可以读出来数据,还有不如意的地方,写此博客整理下思路. 1.BH1750fvi介绍. 这是一个16bit的数字传感器,使用I2C作为通信接口, ...
- golang包管理工具glide安装
1:下载安装glide go get github.com/Masterminds/glide glide的源码以及exe文件在第一个gopath目录,如果不知道哪个是第一个gopath,echo一下 ...