继承
继承:父类可以派生出子类,子类具备父类的属性和方法(子类对象.父类属性或方法),
子类还可添加自己新的属性和方法
提高代码的复用性
原型继承
apply和call继承
混合继承
ES6继承
原型继承
原型继承:用子类的原型对象指向父类的实例化对象
子类.prototype = new 父类构造函数()
作用:子类实例化对象可以直接使用父类创造的属性和方法
并且子类可以添加新的属性和方法
子类的实例化对象,是如何访问父类的属性和父类的方法,及子类的属性和子类的方法
原型图:
子类对象可以直接自身new出的属性,通过_proto_可以访问该类原型对象上的属性和方法,
该类原型对象指向其父类的实例化对象,所以可以访问父类的属性
父类的实力对象的_proto_也指向自身类的prototype,所以可以访问父类原型对象的属性和方法
---------------------------
原型链:
多个类纵向继承,在访问任意属性时,先在自身查找该属性,找不到去原型找,在找不到就去找父级元素,依次向上找
向上查找,祖宗类都找不到,就报错
缺陷:
1.无法在子类对象构造时,初始化父类派生给子类的属性
2.必须先实现继承关系,在为子类添加新的方法,否则会覆盖
instanceof
instanceof:判断某个对象是否属于某个类型,针对于引用类型,返回布尔
typeof和instanceof的异同
1.typeof用来判断内置基本类型,number,string,boolean
2.instanceof用来判断引用类型,返回布尔
apply和call"继承"
apply和call"继承":
可以使子类对象在构造时,初始化父类派生给子类的属性
缺陷:
子类对象无法访问原型对象上的属性和方法
混合继承
混合继承:
1.原型继承prototype上的属性和方法
2.apply和call继承属性
ES6继承
class 子 extends 父{}
super代表的是父类的构造方法
super必须写在第一行
class Human{
constructor(id,name){
this.id = id;
this.name = name;
}
eat(){
console.log("Human eat");
}
}
class Student extends Human{
constructor(id,name,score){
super(id,name);
this.score = score;
}
study(){
console.log("嘤嘤嘤");
}
}
let s = new Student(1,"老王",100);
console.log(s.id,s.name,s.score);
s.eat();
s.study();
深拷贝和浅拷贝
拷贝:用已有对象初始化一个新的对象
内置类型和引用类型在内存中存储的区别:
内置基本类型:
只有一块栈空间,存储的是数据本身
引用类型:
有两块空间,一块栈空间,一块堆空间
栈存储的是堆空间的地址
堆存储的是真正的数据
深浅拷贝只针对于引用类型
let arr = new Array(1,2,3)
浅拷贝:只拷贝地址,但并不开辟空间,两个对象共享同一空间,其中一个改变了数值,另一个也会被修改
// let arr1 = arr
// arr[0] = "强烈抗议"
// console.log(arr)
// console.log(arr1)
深拷贝:开辟空间且赋值,两个对象都有独立的空间,被拷贝的对象,只是和原对象数值相同
// let arr = new Array(1,2,3)
// let arr1 = []
// for(let i=0
// arr1.push(arr[i])
// }
// arr[0] = 82
// console.log(arr)
// console.log(arr1)
function Student(id,name){
this.id = id
this.name = name
}
Student.prototype.copy = function(){
let item = new Student(this.id,this.name)
return item
}
let s1 = new Student(1,"老王")
let s2 = s1.copy()
s1.name = "佩洛西"
console.log(s1,s2)