1、原型链继承

核心: 将父类的实例作为子类的原型

缺点:  父类新增原型方法/原型属性,子类都能访问到,父类一变其它的都变了

        function Person (name) {
this.name = name;
}; Person.prototype.getName = function () { //对原型进行扩展
return this.name;
}; function Parent (age) {
this.age = age;
}; Parent.prototype = new Person('老明'); //这一句是关键 //通过构造器函数创建出一个新对象,把老对象的东西都拿过来。 Parent.prototype.getAge = function () {
return this.age;
}; // Parent.prototype.getName = function () { //可以重写从父类继承来的方法,会优先调用自己的。
// console.log(222);
// }; var result = new Parent(22);
console.log(result.getName()); //老明  //调用了从Person原型中继承来的方法(继承到了当前对象的原型中)  
console.log(result.getAge()); //22   //调用了从Parent原型中扩展来的方法

2、构造继承

基本思想
借用构造函数的基本思想就是利用call或者apply把父类中通过this指定的属性和方法复制(借用)到子类创建的实例中。
因为this对象是在运行时基于函数的执行环境绑定的。也就是说,在全局中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。
call、apply 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。 所以,这个借用构造函数就是,new对象的时候(new创建的时候,this指向创建的这个实例),创建了一个新的实例对象,
并且执行Parent里面的代码,而Parent里面用call调用了Person,也就是说把this指向改成了指向新的实例,
所以就会把Person里面的this相关属性和方法赋值到新的实例上,而不是赋值到Person上面,
所以所有实例中就拥有了父类定义的这些this的属性和方法。 因为属性是绑定到this上面的,所以调用的时候才赋到相应的实例中,各个实例的值就不会互相影响了。

核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)

缺点: 方法都在构造函数中定义, 只能继承父类的实例属性和方法,不能继承原型属性/方法,无法实现函数复用,每个子类都有父类实例函数的副本,影响性能

      function Person (name) {
this.name = name;
this.friends = ['小李','小红'];
this.getName = function () {
return this.name;
}
}; // Person.prototype.geSex = function () { //对原型进行扩展的方法就无法复用了
// console.log("男");
// }; function Parent = (age) {
Person.call(this,'老明');  //这一句是核心关键
//这样就会在新parent对象上执行Person构造函数中定义的所有对象初始化代码,
// 结果parent的每个实例都会具有自己的friends属性的副本
this.age = age;
}; var result = new Parent(23);
console.log(result.name);    //老明
console.log(result.friends);  //["小李", "小红"]
     console.log(result.getName());  //老明
     console.log(result.age);    //23
     console.log(result.getSex());  //这个会报错,调用不到父原型上面扩展的方法

3、组合继承

组合继承(所有的实例都能拥有自己的属性,并且可以使用相同的方法,组合继承避免了原型链和借用构造函数的缺陷,结合了两个的优点,是最常用的继承方式)

核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后再通过将父类实例作为子类原型,实现函数复用

缺点:调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

        function Person  (name) {
this.name = name;
this.friends = ['小李','小红'];
}; Person.prototype.getName = function () {
return this.name;
}; function Parent (age) {
Person.call(this,'老明');  //这一步很关键
this.age = age;
}; Parent.prototype = new Person('老明');  //这一步也很关键
var result = new Parent(24);
console.log(result.name);    //老明
result.friends.push("小智");  //
console.log(result.friends);  //['小李','小红','小智']
console.log(result.getName());  //老明
console.log(result.age);    //24 var result1 = new Parent(25); //通过借用构造函数都有自己的属性,通过原型享用公共的方法
console.log(result1.name);  //老明
console.log(result1.friends);  //['小李','小红']

4、寄生组合继承

核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点

缺点:堪称完美,但实现较为复杂

        function Person(name) {
this.name = name;
this.friends = ['小李','小红'];
} Person.prototype.getName = function () {
return this.name;
}; function Parent(age) {
Person.call(this,"老明");
this.age = age;
} (function () {
var Super = function () {}; // 创建一个没有实例方法的类
Super.prototype = Person.prototype;
Parent.prototype = new Super(); //将实例作为子类的原型
})(); var result = new Parent(23);
console.log(result.name);
console.log(result.friends);
console.log(result.getName());
console.log(result.age);

javascript 面向对象(实现继承的几种方式)的更多相关文章

  1. javascript中实现继承的几种方式

    javascript中实现继承的几种方式 1.借用构造函数实现继承 function Parent1(){ this.name = "parent1" } function Chi ...

  2. 深入理解JavaScript之实现继承的7种方式

    1.原型链继承 核心:将父类的实例作为子类的原型 首先,要知道构造函数.原型和实例之间的关系:构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个原型对象的指针. func ...

  3. javascript(js)创建对象的模式与继承的几种方式

    1.js创建对象的几种方式 工厂模式 为什么会产生工厂模式,原因是使用同一个接口创建很多对象,会产生大量的重复代码,为了解决这个问题,产生了工厂模式. function createPerson(na ...

  4. 前端知识体系:JavaScript基础-原型和原型链-实现继承的几种方式以及他们的优缺点

    实现继承的几种方式以及他们的优缺点(参考文档1.参考文档2.参考文档3) 要搞懂JS继承,我们首先要理解原型链:每一个实例对象都有一个__proto__属性(隐式原型),在js内部用来查找原型链:每一 ...

  5. js 实现继承的6种方式(逐渐优化)

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  6. js实现继承的5种方式 (笔记)

    js实现继承的5种方式 以下 均为 ES5 的写法: js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承 ...

  7. [转]javascript指定事件处理程序包括三种方式:

    javascript指定事件处理程序包括三种方式: (1):DOM0级事件处理程序 如: 代码如下: var btn=document.getElementById("mybtn" ...

  8. JavaScript对象属性访问的两种方式

    JavaScript对象属性访问的两种方式 object.attribute object["attribute"] 例如: var employees = [ { "f ...

  9. js 实现继承的几种方式

    //js中实现继承的几种方式 //实现继承首先要有一个父类,先创造一个动物的父类 function Animal(name){ this.name = name; this.shoot = funct ...

随机推荐

  1. [转] #!/bin/sh & #!/bin/bash区别

    [From] http://blog.51cto.com/meiling/1826201 在shell脚本的开头往往有一句话来定义使用哪种sh解释器来解释脚本.目前研发送测的shell脚本中主要有以下 ...

  2. Flutter FormatException: Bad UTF-8 encoding 0xc3 (at offset 172)

    是文件编码问题. 1,打开 Android Studio 进入设置界面 Ctrl + Alt + S 或 File --> Settings 打开如下界面: 2,将 Project Encode ...

  3. PIE SDK彩色标准化融合

    1.算法功能简介 色彩标准化融合对彩色图像和高分辨率图像进行数学合成,从而使图像得到锐化.色彩归一化变换也被称为能量分离变换( Energy Subdivision Transform),它使用来自融 ...

  4. python学习10-内置函数 迭代 二分法/面向对象初识(转载)

    一.匿名函数 形式: lambda 形参:返回值 lambda表示的是匿名函数. 不需要用def来声明, 一句话就可以声明出一个函数.匿名函数不是说一定没名字,而是他们的名字统一称为“lambda”, ...

  5. Linux Jenkins

    部署与运行: Jenkins 依赖于 Tomcat 才能跑起来,把 Jenkins 的 jenkins.war 文件放到 Tomcat 的安装目录的 webapps 目录下,配置好端口,正常访问 lo ...

  6. git——合并分支

    A将自己的本地代码提交到远程A分支,此时master主干上有B新提交的代码,如果此时A把自己的代码merge到主干,会有冲突,那怎么办? 1.A将自己的代码提交到自己的A分支 2.git fetch ...

  7. FileSearch.java

    !=fileList.size()) { ]) { fileOutputStream.write(bytes; i < files.length; i++) {// 将其中的文件夹遍历出来,并调 ...

  8. pip install xxx -i https://pypi.tuna.tsinghua.edu.cn/simple

    pip install xxx -i https://pypi.tuna.tsinghua.edu.cn/simple 快速下载

  9. IDEA 导入cordova3.5工程目录注意事项

    IDEA 导入cordova3.5工程目录注意事项 1 eclipse很不稳定,有很多小问题.平时我自己用idea,但是当用cordova3.5创建好工程目录是,用eclipse导入时没有问题的.但是 ...

  10. word 摘要

    word 使用心得 定义快捷键 Tools -> Customize keyboard 自定义快捷键 cmd + L, 左对齐; cmd + R, 右对齐; cmd + E, 居中对齐 cmd ...