继承与多态
引入问题一、继承1. 步骤(1) 找到所有子对象共同的父对象(2) 将所有子对象公共的方法定义添加到共同的父对象中(3) 所有子对象因继承关系而直接使用父对象中公共的方法2. 原型中this的指代3.自有属性和共有属性4.内置类型的原型对象:11种内置类型 (背)5. 原型链:二、多态1.override重写图解引入问题
构造函数只能重用代码结构,但是浪费内存。
(1)凡是放在构造函数中的方法定义,每创建一个新对象,都要重复创建这个方法对象的副本!
所以,构造函数中不应该包含方法的定义!
一、继承
(1)定义:父对象的成员,子对象无需重复创建就可直接使用。
既可重用代码, 又可节约内存
(2)何时使用?
只要同一类型多个对象都需要公共的方法定义时,就要用继承实现
1. 步骤
(1) 找到所有子对象共同的父对象
a.定义每个构造函数时都会自带一个原型对象——prototype
b.可通过"构造函数.prototype"属性访问到这个暂时为空的原型对象
c. new的第二步:
让新创建的子对象自动继承构造函数的原型对象
new 会自动设置新子对象:
__proto__=构造函数.prototype
只有从__proto__
指出去的关系才是继承
(2) 将所有子对象公共的方法定义添加到共同的父对象中
如何向原型对象中添加新的共有属性和方法:
只能强行赋值:
构造函数.prototype.共有方法=function(){... }构造函数.prototype.共有属性=属性值
(3) 所有子对象因继承关系而直接使用父对象中公共的方法
用子对象.访问对象成员时,js引擎先在子对象内部查找自有的属性。
如果子对象没有,则js引擎会自动沿_ _proto_ _
属性去父元素查找。
如果在父元素中找到了想要的属性或方法,则和访问子对象的方法一样调用。
强调:构造函数中一定不要包含方法的定义。所有方法都应该集中定义到原型对象中一份。所有子对象共用。
2. 原型中this的指代
原型对象(prototype)中的this
->将来调用这个共有函数的.前的某个子对象。——谁调用指谁
//构造函数中不能定义方法function Student(sname,sage){this.sname=sname;this.sage=sage;}//要定义的方法全部写在Student的原型对象中,成为公共函数Student.prototype.intr=function(){// this在此处只定义,不调用console.log(`I'm ${this.sname}, I'm ${this.sage}`)}var erya1=new Student("erya1",11)var erya2=new Student("erya2",12);// 调用公共函数,this被调用,this->'.'前对象erya1erya1.intr();// 调用公共函数,this被调用,this->'.'前对象erya2erya2.intr();
验证子孩子的父亲是不是Student的老公
console.log(erya1.__proto__==Student.prototype);console.log(erya2.__proto__==Student.prototype);
结果显示true
3.自有属性和共有属性
自有属性: 保存在子对象内部,只归当前子对象自有的属性共有属性:保存在父对象(原型对象)中,归多个子对象共有的属性以下图为例,图中自有属性是name,共有属性是intr
3. 获取属性值,都可用:子对象.属性名
如果js引擎发现,要使用的属性不在子对象中,则自动延_proto_属性向父对象继续查找要用属性。
function Student(sname,sage) {this.sname=sname;this.sage=sage;}Student.prototype.className="1班";var erya1=new Student("erya1",11);var erya2=new Student("erya2",12);console.log(erya1);console.log(erya2);console.log(erya1.className, erya2.className);//1班 1班
4. 修改属性值
1). 自有属性:
子对象.属性名=属性值;
2). 共有属性:
必须用原型对象修改:构造函数.prototype.共有属性=新值
错误后果:不会修改原型对象中的共有属性,而且还会给当前子对象添加一个同名的自有属性。
在这个属性的使用上,这个子对象无法再与其他子对象同步
//修改属性值//错误: // lilei.className="初二2班";//正确:Student.prototype.className="2班";console.log(erya1.className, erya2.className);//2班 2班
4.内置类型的原型对象:
内置类型: ES标准中规定的,浏览器已经实现,我们可以直接使用的类型。
11种内置类型 (背)
String, Number, BooleanArray, Date, RegExp, Math(不是类型,已经是一个{}对象)ErrorFunction Objectglobal(全局作用域对象,在浏览器中被window代替)类型:
一种类型=构造函数+原型对象
构造函数:创建子对象原型对象:为所有子对象保存共有的成员(属性值和方法)
tip:
1.其实11种内置类型中的九种类型,也都由构造函数和原型对象组成。也都可以new创建子对象。
2.查看该类型共有哪些API:类型名.prototype
3.原型对象中没有提供的功能,我们可以自定义一个函数,保存到原型对象中:
构造函数.prototype.新方法=function(){...}
5. 原型链:
原型链:由多级父对象逐级继承形成的链式结构
保存着一个对象可用的所有属性和方法
控制着属性和方法的使用顺序:
先自有再共有——就近原则!
二、多态
定义:同一个函数,在不同情况下表现出不同的状态
分类:
重载overload :同一个函数,输入不同的参数,得到不同的返回值
Javascript(二)——函数(重载、回调)重写override
1.override重写
function Student(sname,sage){this.sname=sname;this.sage=sage;}//在顶级的父类型Object中的原型对象已经有一些共有方法(toString……)//在Student中为所有学生重写好用的toString()Student.prototype.toString=function(){return `{ sname:${this.sname}, sage:${this.sage} }`}var erya=new Student("erya",11)var arr=[1,2,3];var now=new Date();console.log(erya.toString())console.log(arr.toString())console.log(now.toString())
输出结果如下:
图解
①调用函数时,Student、Array和Date对象的构造函数和原型对象以及生成的子对象继承关系如下:
②隐藏存在一个最顶层父类型对象Object,在Object的原型对象中有自带的方法,以toString()为例,每个子对象都可以直接使用Object的toString方法
但是有时候直接使用不满足我们需求,这时可以对其进行重写
③重写
Array对象在它的原型对象中重写其父级的toString()函数,arr就可以调用重写后的toString
Data对象与Student对象同理
如果觉得《JavaScript——面向对象之继承(原型对象)与多态(重载 重写)》对你有帮助,请点赞、收藏,并留下你的观点哦!