文章目录
一:原型继承
1·1:原型继承的定义
所谓原型继承:就是子类自动的拥有父类的属性和方法,继承可以提高代码的复用性,并且子类可以添加新的属性和方法
继承:让原型对象的值,等于另一个类型的实例,即实现了继承
原型链:一个原型对象指向另一个实例,以此类推,就会构成一个原型链
原型继承:
function animal(name, age) {
this.name = name;
this.age = age;
}
animal.prototype.eat = function() {
console.log(this.age+"岁的"+this.name+ "吃香蕉")
}
//继承的核心语句
monkey.prototype = new animal("大猩猩",20);
function monkey(color){
this.color=color
}
monkey.prototype.behaiour=function(){
console.log("行为")
}
let m=new monkey("嘿黑");
// m.name="猴子";
// m.age=30;
console.log(m.name,m.age,m.color);
m.eat();
m.behaiour()
1·2:原型继承的注意事项
-
必须先要定义原型继承关系,在对子类的自定义属性和方法进行添加
-
继承关系实现后,不能再修改子类的prototype的数值
-
父类里包括引用类型的属性的时候,它会被所有实例共享其值
-
子类实例化对象由父类继承的属性,无法进行初始化
function Animal(name){
this.name = name;
}
Animal.prototype.eat = function(){
console.log("动物用来吃饭");
}
function Human(id){
this.id = id;
}
Human.prototype = new Animal("老王");
Human.prototype.makeTools = function(){
console.log("人可以制作工具");
}
let h = new Human(6);//new Human("小明",9);
console.log(h.name,h.id);
h.eat();
h.makeTools();
let h1 = new Human(16);//new Human("大明",19);
console.log(h1.name,h1.id);
console.log(h instanceof Human )
1·3:instanceof:
判断某一个对象是否为某一个类,返回一个boolean值
对象 instanceof 类
二:深拷贝与浅拷贝
2·1:拷贝的定义
拷贝:用已有的一个变量去初始化另一个变量(拷贝只发生在引用数据类型中)
浅拷贝:传参时值只传递了引用空间的地址
深拷贝:开辟空间,且赋值
深拷贝:
function Student(id){
this.id = id;
}
Student.prototype.clone = function(){
//temp存着new出来的堆的空间址
let temp = new Student(this.id);
return temp;
}
//深拷贝:开辟空间且赋值
let s1 = new Student(1);
//给s2返回一个堆空间的地址,且用s1的数值,初始化这个堆空间
let s2 = s1.clone();
s2.id = 456;
console.log(s1.id,s2.id);
浅拷贝:
function Student(id){
this.id = id;
}
let s1 = new Student(1);
let s2 = s1;//浅拷贝
//只拷贝了地址,但是并未开辟空间,等价于配了把钥匙
s2.id = 7;
console.log(s1.id);
三:call和apply的继承
3·1:常规使用
- 解决了原型继承无法在初始化时,修改父类派生的属性
function Animal(name,id){
this.name = name;
this.id = id;
}
function Student(name,id,score){
//借用父类的构造方法
//接收"父类"的属性
Animal.call(this,name,id);
//新添加的属性
this.score = score;
}
let s = new Student("老王",16,100);
console.log(s.name,s.id,s.score);
let s1 = new Student("小明",26,100);
console.log(s1.name,s1.id,s.score);
s1.eat();
3·2:call和apply使用的缺陷
- 无法继承父类原型上的属性和方法
- 单独使用这种借用的模式,所有要继承的属性和方法都要在父类型的构造函数里定义,特别是实例共享的属性和方法也写在构造函数里,那么这样会浪费内存
四:混合继承
4·1:常规使用
结合前两种方式
- apply与call继承属性
- 原型对象prototype继承方法
function Animal(name,id){
this.name = name;
this.id = id;
}
Animal.prototype.eat = function(){
console.log("Animal eat");
}
function Human(name,id,score){
Animal.apply(this,[name,id]);
this.score = score;
}
Human.prototype = new Animal();
Human.prototype.study = function(){
console.log("Human study");
}
let h = new Human("老王",1,100);
console.log(h.name,h.id,h.score);
h.eat();
h.study();
五:ES6的继承
class Animal{
constructor(name,id) {
this.name = name;
this.id = id;
}
//等价于绑定在原型对象上的方法
eat(){
console.log("Animal eat");
}
}
//extends继承的关键字
class Student extends Animal{
constructor(name,id,score) {
//借用父类的构造方法必须用super关键字
super(name,id);
this.score = score;
}
study(){
console.log("Student study");
}
}
let s = new Student("laowang",66,100);
console.log(s.name,s.id,s.score);
s.eat();
s.study();
六:多态
多态:发出一个消息,不同的对象实现不同的消息响应
- call(对象,该函数的真正参数1,参数2…);
- apply(对象,[参数1,参数2…]);
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,"香蕉","草莓");
eat.call(s,"许仙","皮卡丘");
eat.apply(m,["车厘子","煎饼"]);
eat.apply(s,["大蛇丸","皮卡丘"]);
function eat(food1,food2){
console.log(this.name + ":" + food1 + "," + food2);
}
let m = new Monkey("金刚");
let s = new Snake("美杜莎");
eat.call(m,"香蕉","草莓");
eat.call(s,"许仙","皮卡丘");
eat.apply(m,["车厘子","煎饼"]);
eat.apply(s,["大蛇丸","皮卡丘"]);