原型对象
概念:原型对象,是函数(构造函数)对象的一个属性,它保存着所有实例化对象共享的函数和属性
作用:类有很多的属性和方法,一个类可以有多个实例化对象,每次创建一个实例化对象都要new一个新空间,有些实例化对象拥有相同的属性和方法,为了不浪费空间,则将这些共有的属性和方法共享,保存在原型对象中,这样就只需要开辟一个空间。
写法:
function Student(id, name) {
this.id = id;
this.name = name;
}
Student.prototype.study = function() {
console.log(this.name + ":study")
}
let s1 = new Student(1, "蔡");
let s2 = new Student(2, "帅");
s1.study()
s2.study()
原理:实例化对象new出来的空间中存在一个属性_proto_指针,该指针指向原型对象空间,原型对象空间指向原型对象中存储的数据
为官方类添加自定义方法
let arr = [6, 5, 17, 5, 4, 8];
Array.prototype.PX = function() {
let max = this[0];
for (let i = 0; i < arr.length; i++) {
if (max < this[i]) {
max = this[i]
}
}
return max;
}
console.log(arr.PX())
原型继承(ES5)
概念:让子类原型对象的值等于父类的实例,实现了继承
作用:子类可以继承父类的所有属性和方法
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function() {
console.log("animal eat")
}
function Human(id) {
this.id = id;
}
Human.prototype = new Animal("蛋");
Human.prototype.make = function() {
console.log("human make")
}
let h = new Human(9527);
// h.name = "铁蛋";
console.log(h.name);
h.eat()
原型继承的缺陷
- 必须先实现继承关系,才能给子类原型对象添加属性和方法
- 一旦实现原型继承,则子类原型对象的值不能再修改(注意是值不能再修改,不是方法和属性)
- 由父类派生给子类的属性不可以初始化(子类属性值跟随父类属性值)
函数对象call和apply方法
语法:函数对象.call(被改变的this指向,函数对象的参数1,参数2...)
作用:改变函数的this指向,将函数和类进行解耦
function Monkey(name) {
this.name = name;
}
function Snake(name) {
this.name = name;
}
function eat(food1, food2) {
console.log(this.name + ":" + food1 + " " + food2);
}
let m = new Monkey("熏悟空");
let s = new Snake("白素贞");
eat.call(m, "lala", "heihei");
eat.apply(m, ["桃子3", "123"]);
bind、apply、call的异同
- 都是用来改变this指向的
- bind针对于匿名函数,apply和call针对有名函数
- apply第二个参数是一个数组
- bind是生成一个新的函数对象,apply和call是函数调用
call、apply继承(ES5)
概念:构造方法也是方法,则可以利用call、apply改变构造方法的this指向,并传入新参数,达到继承父类属性的效果
作用:可以在继承时将父类派生给子类的属性初始化
注意:该方法只适用于ES5且不能继承父类原型对象中的方法和属性
function Human(name, id) {
this.name = name;
this.id = id;
}
Human.prototype.eat = function() {
console.log("human eat")
}
function Student(name, id, score) {
Human.call(this, name, id);
this.score = score;
}
let s = new Student("lalala", 551, 100);
console.log(s.name);
混合继承(ES5)
概念:用call、apply继承属性,再用原型继承方法,解决了派生属性问题,以及用call、apply 原型对象中的属性和方法无法继承问题
function Human(name, id) {
this.name = name;
this.id = id;
}
Human.prototype.eat = function() {
console.log("human eat")
}
function Student(name, id, score) {
Human.call(this, name, id);
this.score = score;
}
Student.prototype = new Human();
Student.prototype.study = function() {
console.log("student study");
}
let s = new Student("啦啦", 1, 100);
console.log(s);
s.eat()
ES6继承
语法:class 子类 extends 父类
super()
作用:子类继承了父类的属性和方法
class Animal{
constructor(name) {
this.name=name;
}
eat(){
console.log("animal eat")
}
}
class Human extends Animal{
constructor(name,id) {
super(name);
this.id=id;
}
study(){
console.log("human study")
}
}
let h=new Human("laowang",111);
console.log(h.name);
h.eat()
注意:
- super()是借用父类的构造方法,super方法必须写在第一行
- es6写法可初始化原型继承父类派生给子类的属性值
instanceof
概念:判断该对象是否符合该类,返回布尔值,注意继承关系,子对象符合父类,反之不行
语法:实例化对象 instanceof 类名