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. 自执行函数的预解释: 不进行预就解释, 执行 ...
随机推荐
- Apache Hadoop 2.9.2 的Federation架构设计
Apache Hadoop 2.9.2 的Federation架构设计 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 能看到这篇文件,说明你对NameNode的工作原理想必已经了如 ...
- Linux基础命令(三)——>文件过滤及内容编辑处理命令
1.cat 合并文件或查看文件内容 基本功能:cat test.txt 查看文件内容 也可以多文件显示 cat test1.txt test2.txt >test3.txt ...
- object-fit、object-position 属性
object-fit和object-position之间的关系有点类似于background-size和background-position object-fit: object-fit:fill( ...
- Response.Write()方法响应导致页面字体变大的解决办法
关于ASP.NET中用Response.Write()方法响应导致页面字体变大的解决办法 最近研究了ASP.NET,发现一个问题,比方说在页面里面有个Button,要点击以后要打开新窗口,而且 ...
- KAGGLE竟赛
KAGGLE竟赛 关于kaggle的竟赛规则我们勇闯组做出了一些说明,大家可以借鉴一下如何参加kaggle,参加kaggle大赛的一些注意事项,自己参加一些项目,一定会使你的知识量得到质的提升 这是链 ...
- SqlServer查询某数据在某表某列中
create proc spFind_Column_In_DB ( @type int,--类型:为文字类型.为数值类型 @str nvarchar(100)--需要搜索的名字 ) as --创建临时 ...
- PyTorch中ReLU的inplace
0 - inplace 在pytorch中,nn.ReLU(inplace=True)和nn.LeakyReLU(inplace=True)中存在inplace字段.该参数的inplace=True的 ...
- dba_segements 没有所有的表的信息
这是oracle11g新增的功能,假设一个一般的用户user新建了一张表user_table,这时切换到sys用户查看dba_segments 查看user_table的信息,发现dba_segmen ...
- 解决关于win10下eclipse代码格式化不生效问题
今日,在写代码的时候遇到在eclipse中ctrl+shift+f格式化代码不生效的问题,原本以为是和热键冲突,所以关闭了搜狗输入法的简体和繁体的切换方式,但是发现,还是没有生效,所以,想到修改ecl ...
- Ubuntu VMware workstation虚拟机清理缓存文件获得更大硬盘空间
1 前言 VMware workstation 15 Player经常使用拖拉复制文件到虚拟机,从而导致了drag_and_drop特别大,占用了很多硬盘空间. fanbi@ubuntu:~/.cac ...