原型的作用:1.将公共部分放入原型中,这样构造出的多个实例对象的公共部分只会占用一个公共空间,实现数据共享和节省内存空间
2.通过原型实现继承:构造函数模拟 "类"这个面向对象的概念,JS基于对象,基于构造函数的原型对象实现继承 如何实现继承?
1.改变原型对象的指向:将子类构造函数(B)的prototype指向父类构造函数(A)的一个实例化对象(a),那么这个子类构造函数构造出的实例化对象
(b)就可以访问父类(A)的属性和方法
缺陷:由于B的prototype改变,那么保存在原来的B的prototype里的属性和方法就无法访问了,构造出的b无法获得这些属性和方法
解决方法:先进行原型指向的改变,再定义子类的原型属性和方法,这样子类后定义的原型属性和方法就定义到了父类的实例对象中
 var Person = function(name,sex){
this.name = name;
this.sex= sex;
}
Person.prototype.eat = function () {
console.log("吃");
}; var Student = function(score){
this.score = score;
};
Student.prototype.study = function () {
console.log("学习");
}; Student.prototype = new Person("xiaoming","man"); var stu = new Student(66);
stu.eat(); //可以调用
stu.study() //报错,由于改变了prototype指向,无法寻找到study这个方法

先改变原型指向,后定义原型方法:

 var Person = function(name,sex){
this.name = name;
this.sex= sex;
}
Person.prototype.eat = function () {
console.log("吃");
}; var Student = function(score){
this.score = score;
}; Student.prototype = new Person("xiaoming","man");
Student.prototype.study = function () {
console.log("学习");
}; var stu = new Student(66);
stu.eat(); //可以调用
stu.study(); //可以调用
console.log(Student.prototype);
/* name:"xiaoming"
sex:"man"
study:ƒ () 可以看出后定义的方法写入了Student.prototype即这个new Person实例化对象中了
__proto__:Object 这个隐式原型指向Person.prototype,里面有eat方法
*/

如果使用这个方式实现多代继承,那么每一代都需要先改变原型指向,在定义原型属性和方法。

如果使用这个方式实现多代继承,那么每一代都需要先改变原型指向,在定义原型属性和方法。
在新的原型链中,原本子代的构造函数的prototype消失,新的prototype即是父代的一个实例化对象。
而子代实例对象的__proto__都指向其父代的这个实例化对象,原型链就成为实例化对象之间的指向关系,直到最高级祖先的构造函数的prototype 仍然存在的问题:改变子代prototype的指向,指向父代的一个实例对象,那么这个实例对象的属性和方法就已经被初始化了,即继承过来的属性和方法是已经确定的,无法在构建子代实例化对象时重新初始化这些继承下来的属性和方法
2.借用构造函数实现继承
* 利用call方法或者apply方法借用父代的构造函数
* 在子代构造函数中添加
* 父代构造函数.call(this.父代形参列表)
* 同时也要在子代的形参列表中加入父代的形参列表
* 想当于在子代构造函数中也写了父代构造函数中的定义属性和方法的那些代码
* 所以优点:可以在子代构造函数实例化对象时自己初始化父代的属性和方法,不再是继承到固定的实现和方法
* 所以缺陷:没有在子代的原型和父代原型之间形成原型链,所以无法访问父代原型里的方法和属性
  var Person = function (name) {
this.name= name;
this.say = function () {
console.log("Hi,I am" + this.name);
};
};
Person.prototype.eat = function () {
console.log("吃");
};
Person.prototype.sex = "man"; //父代原型里的属性 var Student= function (score,name) {
this.score = score;
Person.call(this,name);
// Person.apply(this,[name]);
};
Student.prototype.test = function () {
console.log("考试");
}; var stu1 = new Student(80,"小王");
console.log(stu1.name);
stu1.say(); //可以调用父代构造函数里的的属性和方法 console.log(stu1.sex); //undefined
stu1.eat(); //报错------>无法通过借用构造函数的方法继承父类原型里的属性和方法

3.组合继承:结合以上两种方法:

*   1):改变prototype指向(这时不需要再new父代实例化对象时传入参数),子代和父代之间形成原型链,可以继承父代原型里的属性和方法
* 2):借用父代的构造函数,实现继承父代构造函数内的属性和方法,还可以在实例化子代时自己初始化这些属性和方法
    var Person = function (name) {
this.name= name;
this.say = function () {
console.log("Hi,I am" + this.name);
};
};
Person.prototype.eat = function () {
console.log("吃");
};
Person.prototype.sex = "男"; //父代原型里的属性 var Student= function (score,name) {
this.score = score;
Person.call(this,name);
// Person.apply(this,[name]);
};
Student.prototype = new Person();
Student.prototype.test = function () {
console.log("考试");
}; var stu2 = new Student(80,"小王");
console.log(stu2.name);
stu2.say(); //可以调用父代构造函数里的的属性和方法 console.log(stu2.sex);
stu2.eat(); //可以调用父代原型里的属性和方法 console.log(stu2.score);
stu2.test(); //当然可以正常调用子代的属性和方法
												

Js实现继承的方法的更多相关文章

  1. JS 实现继承的方法 ES6 and ES5

    继承 ES6 方法  (类的继承) ES6中有一个属性的 extends 语法: ​ • class Father {} ​ • class Son extends Father{} ​ 注意:是子类 ...

  2. js中继承的方法总结(apply,call,prototype)

    一,js中对象继承 js中有三种继承方式 1.js原型(prototype)实现继承 代码如下: <SPAN style="<SPAN style="FONT-SIZE ...

  3. js 继承 对象方法与原型方法

    js函数式编程确实比很多强语言使用灵活得多,今天抽了点时间玩下类与对象方法调用优先级别,顺便回顾下继承 暂时把原型引用写成继承 先看看简单的两个继承 var Parent = function(){} ...

  4. JS中通过call方法实现继承

    原文:JS中通过call方法实现继承 讲解都写在注释里面了,有不对的地方请拍砖,谢谢! <html xmlns="http://www.w3.org/1999/xhtml"& ...

  5. 各种实现js继承的方法总结

    昨天主要介绍了原型,在js中,原型,原型链和继承是三个很重要的概念,而这几个概念也是面试中经常会被问到的问题,今天,就把昨天还没总结的原型链和继承继续做一个整理,希望大家一起学习,一起进步呀O(∩_∩ ...

  6. js各继承方法的优缺点

    在js中有很多种继承的方法,下面总结这些方法的优缺点. ####1.原型链继承 优点: 非常纯粹的继承关系,实例是子类的实例,也是父类的实例 父类新增原型方法/原型属性,子类都能访问到 简单,易于实现 ...

  7. 由js apply与call方法想到的js数据类型(原始类型和引用类型)

    原文地址:由js apply与call方法想到的js数据类型(原始类型和引用类型) js的call方法与apply方法的区别在于第二个参数的不同,他们都有2个参数,第一个为对象(即需要用对象a继承b, ...

  8. JS对象继承篇

    JS对象继承篇 ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的 原型链 其基本思路是利用原型让一个引用类型继承另一个引用类型的属性和方法 function Person() ...

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

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

随机推荐

  1. 关于STM32CubeMX使用LL库设置PWM输出

    HAL和LL库 HAL是ST为了实现代码在ST家族的MCU上的移植性,推出的一个库,称为硬件抽象层,很明显,这样做将会牺牲存储资源,所以项目最后的代码比较冗余,且运行效率大大降低,运行速度受制于fla ...

  2. 20175126《Java程序设计》第七周学习总结

    # 20175126 2016-2017-2 <Java程序设计>第七周学习总结 ## 教材学习内容总结 - 本周学习方式主要为手动敲代码并理解内容学习. - 学习内容为教材第八章,本章主 ...

  3. Struct2 基础介绍

    前面花一周时间学习了servlet+jsp+mysql, 并且简单实现了登录注册等操作.对Servlet应用有了基础了解! 关于Struct2这个经常听说,但是自己没有用过.今天在这学习总结下,目的是 ...

  4. spring注解式参数校验

    很痛苦遇到大量的参数进行校验,在业务中还要抛出异常或者返回异常时的校验信息,在代码中相当冗长,今天我们就来学习spring注解式参数校验. 其实就是:hibernate的validator. 开始啦. ...

  5. Vue仿string.format

    Vue.prototype.$stringFormat = function stringFormat (formatted, args) { for (let i = 0; i < args. ...

  6. php使用redis的有序集合zset实现延迟队列

    延迟队列就是个带延迟功能的消息队列,相对于普通队列,它可以在指定时间消费掉消息. 延迟队列的应用场景: 1.新用户注册,10分钟后发送邮件或站内信. 2.用户下单后,30分钟未支付,订单自动作废. 我 ...

  7. php操作redis数据库方法总结

    一.安装php_redis扩展,用以操作redis http://pecl.php.net/package/redis 选择自已系统php版本对应的扩展. 二.redis连接与验证 <?php ...

  8. PHP整理--MySQL--DOS命令操作数据库

    一.MySQL:关系型数据库,存在表的概念. MySQL的结构:数据库可以存放很多表,每张表可以存放多个字段,每个字段可以存放多个记录. 二.Dos操作数据库 用PHPStudy终端➡其他选项菜单➡M ...

  9. slot-scope

    插槽,也就是slot,是组件的一块HTML模板,这块模板显示不显示.以及怎样显示由父组件来决定. 实际上,一个slot最核心的两个问题在这里就点出来了,是显示不显示和怎样显示. 由于插槽是一块模板,所 ...

  10. docker 删除所有none的镜像

    docker images|grep none|awk '{print $3}'|xargs docker rmi