一、原型链继承

每个构造函数都有一个原型对象,原型对象中都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。当原型对象等于另外一个类型的实例即继承。

缺点:如果某一个构造函数实例对象修改了原型对象上的属性值和方法,则也会影响其他实例对象

//定义父构造函数类型function Animal(){this.name = "animal" }Animal.prototype = {sayName : function(){console.log(this.name);}}
//定义子类类型
function Dog(){this.color = "灰色"
}//通过将子对象的原型对象指向父对象的一个实例来完成继承Dog.prototype = new Animal();Dog.prototype.constructor = Dog;

子构造函数的原型指向父构造函数的实例

子构造函数Dog的原型指向父构造函数Animal的实例

Dog.prototype = new Animal();//嫁给有钱人家的孩子

Dog.prototype.constructor = Dog;//建立起夫妻关系

二、经典继承

也称 "伪造对象" 或 ”借用构造函数",在子类型构造函数的内部调用超类型构造函数。函数不过是在特定环境中执行代码的对象,因此通过apply(),call()方法可以在(将来)新建对象上执行构造函数,即在子类型对象上执行父类型函数中定义的所有对象初始化的代码。结果每个子类实例中都具有了父类型中的属性以及方法

 function Animal(name){this.name = name;this.colors = ["red","gray"];}function Dog(name){//继承了AnimalAnimal.call(this,name);this.color = "gray";}Animal.prototype.sayName = function(){alert(this.name);}

三、组合函数(原型链继承+经典继承)

组合函数(原型链继承+经典继承)

也称“伪经典继承”,将原型链和借用构造函数的技术组合在一起。原理是:使用原型链实现对原型属性和方法的继承,而通过借用构造函数实现对实例属性的继承。

 function Animal(name){this.name = name;this.colors = ["red","gray"];}function Dog(name){//经典继承,继承了Animal(属性)Animal.call(this,name);this.color = "gray";}Animal.prototype.sayName = function(){alert(this.name);}//原型链继承,继承了方法Dog.prototype = new Animal();Dog.prototype.constructor = Animal;
原理是:使用原型链实现对原型属性和方法的继承,而通过借用构造函数实现对实例属性的继承

实例:

// 1、原型链的继承
function Dog2() {}
// 在prototype中定义的属性和方法,所有的实例都共享
Dog2.prototype.name = 'xiaobai';
Dog2.prototype.age = 2;
Dog2.prototype.sayName = function() {console.log(this.name);}// 原型链继承的操作
function Dog_son() {}
Dog_son.prototype = new Dog2(); //当原型对象等于另外一个类型的实例即继承。
Dog_son.prototype.constructor = Dog_son(); //这样是为了使Dog_son的构造函数变为原来的,重新指定一下var d1 = new Dog_son();
console.log(d1);
d1.sayName();// -------------------------------
// 2、经典继承(伪继承)
console.log('经典继承')function Animal(name, age) {this.name = name;this.age = age;
}function Dog(name, age, color) {Animal.call(this, name, age); //经典继承,好熟悉this.color = color;
}
var dl = new Dog('小白', '2', 'white');
console.log(d1);// ------------------------------------
// 3.组合模式
// 原型链加借用构造函数
function Animal_1(name, age) {this.name = name;this.age = age;
}
Animal_1.prototype.sayName = function() {console.log(this.name);
}function Dog(name, age, color) {Animal.call(this, name, age);this.color = color;
}
Dog.prototype = new Animal_1(); //当原型对象等于另外一个类型的实例
Dog.prototype.constructor = Dog; //将构造函数设置回来
Dog.prototype.sayColor = function() {console.log(this.color);
}

eg深入理解

// 父类
function Father(name) {// 属性this.name = name || 'father',// 实例方法this.sleep = function() {console.log(this.name + "正在睡觉");}
}
// 原型方法
Father.prototype.look = function(book) {console.log(this.name + "正在看:" + book);}// --------------------------------------------// 1.原型继承// 核心:将父类的实例作为子类的原型(并不是把父类中的属性和方法克隆一份一模一样的给子类,而是让子类父类之间增加了原型链接)// 特点:父类中私有的和公有的都继承到了子类原型上(子类公有的)// 缺点:如果某一个构造函数实例对象修改了原型对象上的属性值和方法,则也会影响其他实例对象
function Son() {}
Son.prototype = new Father(); //相当于重写了Son的原型
Son.prototype.constructor = Son; //重写原型后把Son原型上的constructor重新指向Son
var son = new Son();
son.sleep() //---------father正在睡觉
son.look('TV') //-------------father正在看:TV
console.log(son) //----------------Son {}  【原型链继承并不是克隆一份】
console.log(Father.prototype.isPrototypeOf(son)) //----------true【在原型链上面】
console.log(son instanceof Son) //---------true
console.log(son instanceof Father) //-------true// ----------------------------------------------// 2.借用构造继承,call继承       【不能继承原型链的方法】// 核心:使用父类的构造函数来增强子类实例// 特点:把父类私有的属性和方法,克隆一份一样的给子类私有的属性,Father执行的时候,把Father的中的this换成Son的实例,由于并不是new Father,所以Father.prototype上的属性无关// 缺点:但没有原型,则复用无从谈起
function Son2() {Father.call(this);// 可以加参数
}
var son2 = new Son2();
son2.sleep(); //--------father正在睡觉
// son2.look('TV');-------没有原型链的方法,会报错
console.log(son2) //----------Son2 { name: 'father', sleep: [Function (anonymous)] }   【不能继承原型链上的方法,所以没有原型链方法】
console.log(Father.prototype.isPrototypeOf(son2)) //-----------false    【原型链还是】
console.log(son2 instanceof Son2) //----------------------------true
console.log(son2 instanceof Father) //--------------------------false     【不能继承原型链上的方法,所以没有原型链方法】// ----------------------------------------------// 3.混合模式继承: 原型继承+call继承// 核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用// 特点:把父类私有的和公有的都变成了子类共有的,但是调用了【两次父类构造函数】,生成了两份实例// 原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承
function Son3(name) {Father.call(this)this.name = name
}
Son3.prototype = new Father(); //父类实例作为子类原型,实现函数复用
Son3.prototype.constructor = Son3;
// 【调用了两次构造函数】
var son3 = new Son3('son3');
son3.sleep() //son3正在睡觉
son3.look('TV') //son3正在看:TV
console.log(son3) //---{ name: 'son3', sleep: [Function (anonymous)] }
console.log(Father.prototype.isPrototypeOf(son3)) //-----------------true 【父类原型链上有】
console.log(son3 instanceof Son3) //-----------------------true
console.log(son3 instanceof Father) //---------------------true

原型链继承

借用构造函数继承

组合式继承

function Son() {}

Son.prototype = new Father(); //相当于重写了Son的原型

Son.prototype.constructor = Son; //重写原型后把Son原型上的constructor重新指向Son

function Son2() {

Father.call(this);

// 可以加参数

}

function Son3(name) {

Father.call(this)

this.name = name

}

Son3.prototype = new Father(); //父类实例作为子类原型,实现函数复用

Son3.prototype.constructor = Son3;

console.log(son) //----------------Son {}  【原型链继承并不是克隆一份】

console.log(Father.prototype.isPrototypeOf(son)) //----------true【在原型链上面】

console.log(son instanceof Son) //---------true

console.log(son instanceof Father) //-------true

// son2.look('TV');-------没有原型链的方法,会报错

console.log(son2) //----------Son2 { name: 'father', sleep: [Function (anonymous)] }   【不能继承原型链上的方法,所以没有原型链方法】

console.log(Father.prototype.isPrototypeOf(son2)) //-----------false    【原型链还是】

console.log(son2 instanceof Son2) //----------------------------true

console.log(son2 instanceof Father) //--------------------------false     【不能继承原型链上的方法,所以没有原型链方法】

console.log(son3) //---{ name: 'son3', sleep: [Function (anonymous)] }

console.log(Father.prototype.isPrototypeOf(son3)) //-----------------true 【父类原型链上有】     

console.log(son3 instanceof Son3) //-----------------------true

console.log(son3 instanceof Father) //---------------------true

// 核心:将父类的实例作为子类的原型(并不是把父类中的属性和方法克隆一份一模一样的给子类,而是让子类父类之间增加了原型链接)

    // 特点:父类中私有的和公有的都继承到了子类原型上(子类公有的)

    // 缺点:如果某一个构造函数实例对象修改了原型对象上的属性值和方法,则也会影响其他实例对象

// 2.借用构造继承,call继承       【不能继承原型链的方法】

    // 核心:使用父类的构造函数来增强子类实例

    // 特点:把父类私有的属性和方法,克隆一份一样的给子类私有的属性,Father执行的时候,把Father的中的this换成Son的实例,由于并不是new Father,所以Father.prototype上的属性无关

    // 缺点:但没有原型,则复用无从谈起

 // 3.混合模式继承: 原型继承+call继承

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

    // 特点:把父类私有的和公有的都变成了子类共有的,但是调用了【两次父类构造函数】,生成了两份实例

    // 原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承
(组合继承最大的问题是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部)

/ --------------------------------------------------------------
// 4.原型式继承
// 创建一个函数,将参数作为一个对象的原型对象
function fun(obj) {function Son4() {}; //构造函数Son4.prototype = obj; //对象的原型对象return new Son4(); //
}
var son4_1 = fun(Father);
var son4_2 = fun(Father);
console.log(son4_1) //Function {}
console.log(Father.prototype.isPrototypeOf(son4_1)) //false
console.log(son4_1 instanceof Father) //false
console.log(son4_1 instanceof fun) //false// 创建一个函数fun,内部定义一个构造函数Son// 将Son的原型对象设置为参数,参数是一个对象,完成继承// 将Son实例化后返回,即返回的是一个实例化对象// 优缺点:跟原型链类似// ------------------------------------------------------// 5.寄生继承// 创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象。// 可以理解为在原型式继承的基础上新增一些函数或属性// (1)原型式继承
function Createobj(obj) {function Son5() {};Son5.prototype = obj;return new Son5();
}
// 上面CreateObj函数 在ECMAScript5 有了一新的规范写法,Object.create(ob) 效果是一样的 , 看下面代码
var son5_1 = Createobj(Father);
var son5_2 = Object.create(Father);
console.log(son5_1.name); // Father
console.log(son5_2.name); // Father
// (2)开始寄生继承
function Jicheng(obj) {// var newobj = Createobj(obj); 两种方式都可以var newobj = Object.create(obj); //写了这个就可以不用上面的了newobj.sayName = function() {console.log("我的名字" + this.name);} //增强对象return newobj; //指定对象
}var son5_3 = Jicheng(Father);
son5_3.sayName()// 6.寄生组合

js对象继承的方式-三种 +三种相关推荐

  1. 细节:js 对象继承的几种模式举例

    原型链继承 function Person(){};Person.prototype = {constructor: Person,name: "Oliver" };functio ...

  2. js对象继承的5种方法

    假设现在有a,b两个函数,b函数的实例想要访问a函数的属性和方法(b想要继承a). 1.原型链继承 通过b函数的原型(b.prototype)指向a的实例(new a())来实现,这种继承方法就称为原 ...

  3. (转)js实现继承的5种方式

    js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承有以下通用的几种方式 1.使用对象冒充实现继承(该种实 ...

  4. JS对象和JSON字符串相互转化总结

    在web开发中,一般情况下需要前端和服务器的交换数据,我们一般使用JSON来完成数据的传输,JavaScript操作的对象是一般是变量:因此我们需要将JSON字符串转换为JS变量,下面总结JS对象和J ...

  5. JavaScript中的面向对象--对象继承

    JavaScript高级程序设计第3版 p162 这里总结一下JavaScript中对象继承的方式,主要有原型链和借用构造函数模式,衍生的出来的有组合式继承.原型式继承.寄生式继承和寄生组合式继承.原 ...

  6. js中自定义对象、json对象、json字符串、普通js对象 --js学习那本书上的

    4.7 自定义对象 JS除了内置对象之外,还允许我们程序自己定义属于我们自己的对象,在JS中自定义对象的方式有2种:通过构造器创建对象,通过初始化器创建对象. 4.7.1 构造器创建对象(原生JS对象 ...

  7. js中自定义对象、json对象、json字符串、普通js对象

    4.7 自定义对象 JS除了内置对象之外,还允许我们程序自己定义属于我们自己的对象,在JS中自定义对象的方式有2种:通过构造器创建对象,通过初始化器创建对象. 4.7.1 构造器创建对象(原生JS对象 ...

  8. java对象实例化的方式

    java对象实例化的方式有以下几种: 1.使用new 2.工厂模式 3.反射 4.clone()方法 5.反序列化方式 /** 实现Cloneable和Serializable接口 */ public ...

  9. js中将字符串转换成json的三种方式

    ECMA-262(E3) 中没有将JSON概念写到标准中,还好在 ECMA-262(E5) 中JSON的概念被正式引入了,包括全局的JSON对象和Date的toJSON方法. 1,eval方式解析,恐 ...

最新文章

  1. O365(世纪互联)SharePoint 之站点个性化
  2. JAVA SE学习day_06:字符流、异常处理
  3. 我的csdnmark
  4. SpringMVC中,前台jsp封装参数,绑定参数,传递参数到后台controller的过程详解
  5. 关于 通过http请求 无法访问Linux下的ftp服务的解决办法!
  6. linux配置环境jdk
  7. java kafka 消费_java编程之Kafka_消费者API详解
  8. Lab 2 - Task v2 SP_22-设计complex multiplication共3个part-verilog设计
  9. java学习(67):匿名内部类
  10. node.js——阿里企业级服务框架Egg搭建
  11. 项目中的textarea遇到的小问题
  12. Euler Tour Tree与dynamic connectivity
  13. 贪心算法(java实现)
  14. Linux如何实现自动文件同步?
  15. 记录ubuntu18.04安装QQ过程
  16. Windows程序设计-位图和位块传输
  17. 为什么要在MD5加密的密码中加“盐”
  18. Word2Vec与文章相似度
  19. 修改Office 2016安装路径的方法
  20. python绘制菱形_用python画菱形

热门文章

  1. 45页完整版PPT深度阐述互联网全网分销解决方案
  2. 将SpringBoot项目制作成Docker镜像并在本机访问
  3. 四种算法求最大公约数
  4. java-鸡生蛋?蛋生鸡?
  5. fixedsys字体 win7_Win7 32位系统怎么显示默认隐藏字体
  6. 欢迎光临寒舍!!!本blog 正在筹建中~~~~~
  7. Android Receiver(听筒模式和扬声器模式,铃音模式)
  8. 基于SpringBoot的在线心理咨询管理系统
  9. 中国艺术研究院唐建教授浅谈八大山人
  10. 快速云:TOSCA和其他云标准化工作停滞不前