继承

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封装一个表格控件
    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种经典继承方式的更多相关文章

  1. JS中三种字符串连接方式及其性能比较

    工作中经常会碰到要把2个或多个字符串连接成一个字符串的问题,在JS中处理这类问题一般有三种方法,这里将它们一一列出顺便也对它们的性能做个具体的比较. 第一种方法  用连接符“+”把要连接的字符串连起来 ...

  2. 详解js中的寄生组合式继承

    寄生组合式继承是js中最理想的继承方式, 最大限度的节省了内存空间. js中的寄生组合式继承要求是: 1.子对象有父对象属性的副本, 且这些不应该保存在子对象的prototype上.       2. ...

  3. js中的原型、继承的一些想法

    最近看到一个别人写的js类库,突然对js中的原型及继承产生了一些想法,之前也看过其中的一些内容,但是总不是很清晰,这几天利用空闲时间,对这块理解了一下,感觉还是有不通之处,思路上没那么条理,仅作为分享 ...

  4. [转]js中几种实用的跨域方法原理详解

    转自:js中几种实用的跨域方法原理详解 - 无双 - 博客园 // // 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同 ...

  5. 关于js中两种定时器的设置及清除(转载)

    1.JS中的定时器有两种: window.setTimeout([function],[interval]) 设置一个定时器,并且设定了一个等待的时间[interval],当到达时间后,执行对应的方法 ...

  6. mybatis中两种取值方式?谈谈Spring框架理解?

    1.mybatis中两种取值方式? 回答:Mybatis中取值方式有几种?各自区别是什么? Mybatis取值方式就是说在Mapper文件中获取service传过来的值的方法,总共有两种方式,通过 $ ...

  7. js中三种定义变量 const, var, let 的区别

    js中三种定义变量的方式const, var, let的区别 1.const定义的变量不可以修改,而且必须初始化. 1 const b = 2;//正确 2 // const b;//错误,必须初始化 ...

  8. JS中几种常见的数组算法(前端面试必看)

    JS中几种常见的数组算法 1.将稀疏数组变成不稀疏数组 /** * 稀疏数组 变为 不稀疏数组 * @params array arr 稀疏数组 * @return array 不稀疏的数组 */ f ...

  9. [js]js中4种无节操的预解释情况

    js中4种无节操的预解释情况 - 1. if语句即使条件不成立,条件里的表达式也会进行预解释. - 2. 匿名函数的预解释: 只对等号左边与解释 - 3. 自执行函数的预解释: 不进行预就解释, 执行 ...

随机推荐

  1. 逆FizzBuzz问题求最短序列

    问题描述 FizzBuzz问题:一个大于0的自然数能整除3,将输出“Fizz”:能整除5,将输出“Buzz”:能整除3和5,将输出“FizzBuzz”:否则输出自己. 逆FizzBuzz问题最短序列: ...

  2. Codeforces Round #554 (Div. 2) B. Neko Performs Cat Furrier Transform(思维题+log2求解二进制位数的小技巧)

    传送门 题意: 给出一个数x,有两个操作: ①:x ^= 2k-1; ②:x++; 每次操作都是从①开始,紧接着是② ①②操作循环进行,问经过多少步操作后,x可以变为2p-1的格式? 最多操作40次, ...

  3. 野路子码农系列(1) 创建Web API

    新工作正式开始了2天,由于客户暂时还没交接数据过来,暂时无事可做.恰逢政佬给某超市做的商品图像识别的项目客户催收了,老板要求赶紧搞个API,于是我就想我来试试吧. 说起API,我其实是一窍不通的,我对 ...

  4. 快速掌握Nginx(二) —— Nginx的Location和Rewrite

    1 location详解 1.location匹配规则 Nginx中location的作用是根据Url来决定怎么处理用户请求(转发请求给其他服务器处理或者查找本地文件进行处理).location支持正 ...

  5. Angular记录(5)

    文档资料 箭头函数--MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_fun ...

  6. checkbox 实现互斥选择

    // mutex 互斥 checkbox 互斥/** 互斥的原理.找到需要互斥的所有的元素.赋值 checked=false; 然后单独赋值 checked=true* */var mutexbox ...

  7. python的多线程

    1.多线程的例子 import threading #首先导入threading模块,这是使用多线程的前提 from time import ctime,sleep def music(func): ...

  8. Object Detection / Human Action Recognition 项目

    https://towardsdatascience.com/real-time-and-video-processing-object-detection-using-tensorflow-open ...

  9. “短路求值(Short-Circuit Evaluation)

        // 逻辑与和逻辑或操作符总是先计算其做操作数,只有在仅靠左操作数的值无法确定该逻辑表达式的结果时,才会求解其右操作数. function aa() { if (null) { console ...

  10. axios formData提交数据 && axios设置charset无效???

    但是这样会出现一个问题,什么问题呢? 我设置了请求头编码utf-8,但是没生效 content-type里面没有出现utf-8???????查了很多资料,说这是axios固有的bug,我....... ...