1.原型链继承
(1)图示如下: 子类继承父类的属性和方法(目的让子类的实例可以调取父类中的属性和方法)

(2)代码举例
//构造函数Person
function Person(){
this.name = "xiaomingming";
this.pets =["maomao","gougou"];
}
Person.prototype.run = function(){
console.log('runrunrun')
}
function Stu(){
this.num = "bengbeng"
}
<!--以下是核心步骤-->
//1.构造父类的实例
var p = new Person();
// 2.设置子类的原型对象
Stu.prototype = p;
// 3.修复constructor指针
Stu.prototype.constructor = Stu;
//全部继承
var stu = new Stu();
console.log(stu);
console.log(stu.num);
console.log(stu.name);
console.log(stu.pets);
问题引入
接以上代码:
//构造函数Person
<script>
function Person(){
this.name = "xiaomingming";
this.pets =["maomao","gougou"];
}
Person.prototype.run = function(){
console.log('runrunrun')
}
function Stu(){
this.num = "bengbeng"
}
<!--以下是核心步骤-->
//1.构造父类的实例
var p = new Person();
// 2.设置子类的原型对象
Stu.prototype = p;
// 3.修复constructor指针
Stu.prototype.constructor = Stu;
//全部继承
var stu = new Stu();
var stu2 = new Stu();
</script>
<script>
1.
stu.name = "Jay"
console.log(stu)
console.log(stu2)
2.
var pets = stu.pets;
pets.push('huhu')
console.log(stu)
console.log(stu2)
</script>
上面结果

接下来值得注意:
1.子类方法要在实现继承后去定义方法2.子类可以重写父类上的属性和方法 代码示例1:
//构造函数Person
function Person(){
this.name = "xiaomingming";
this.pets =["maomao","gougou"];
}
Person.prototype.run = function(hi){
this.hi = 'hi'
console.log('runrunrun')
}
function Stu(){
this.name = 'xinming'
this.num = "bengbeng"
}
Stu.prototype.eat=function(){
console.log('我是继承前定义的eat')
}
//1.构造父类的实例
var p = new Person();
// 2.设置子类的原型对象
Stu.prototype = p;
// 3.修复constructor指针
Stu.prototype.constructor = Stu;
//全部继承
var stu = new Stu();
stu.run();
// stu.eat();
// 1.
stu.name = "Jay"
// 2.
var pets = stu.pets;
pets.push('huhu')
var stu2 = new Stu();
stu2.run();
console.log(stu)
console.log(stu2)
报错:

代码示例2:
//构造函数Person
function Person(){
this.name = "xiaomingming";
this.pets =["maomao","gougou"];
}
Person.prototype.run = function(hi){
this.hi = 'hi'
console.log('runrunrun')
}
function Stu(){
this.name = 'xinming'
this.num = "bengbeng"
}
//1.构造父类的实例
var p = new Person();
// 2.设置子类的原型对象
Stu.prototype = p;
// 3.修复constructor指针
Stu.prototype.constructor = Stu;
Stu.prototype.eat=function(){
console.log('我是继承后定义的eat')
}
Stu.prototype.run=function(bye){
console.log('我是继承后定义的run')
}
//全部继承
var stu = new Stu();
stu.run();
stu.eat();
1.
stu.name = "Jay"
// 2.
var pets = stu.pets;
pets.push('huhu')
var stu2 = new Stu();
stu2.run();
console.log(stu)
console.log(stu2)

总结: 特点1:父类中私有的属性和方法最会都变成子类公有的属性和方法。 特点2:子类可以重写父类上的属性和方法(导致子类其他实例受影响)
2.单独采用构造函数实现继承
function Animal(){
this.species = "动物";
}
Animal.prototype.run=function(){
console.log('animal原型')
}
function Cat(name,color){
this.name = name;
this.color = color;
}
function Cat(name,color){
Animal.apply(this, arguments);
this.name = name;
this.color = color;
}
var cat1 = new Cat("AA猫","黑色");
alert(cat1.species); // 动物
cat1.run()
结果:

构造函数继承总结: 特点:1.CHILD方法中把PARENT当做普通函数执行,让PARENT中的THIS指向CHILD的实例,相当于给CHILD设置了很多私有属性方法 1.只能继承父类私有的属性和方法,(因为是把PARENT当做普通函数执行,和其原型上的属性和方法没有关系) 2.父类私有变成子类私有
关于私有公有我们可以理解为,私有的只是在当前的函数里面起作用,公有的是会依照原型进行继承,是会影响到后续的依靠其创建的实例的属性和方法。
3.在原型继承基础上+借助构造函数继承(解决共享问题)
完整代码:
<script>
/**
* 构造函数Person
*/
function Person(name,pets){
this.name = name;
this.pets =pets;
}
Person.prototype.run = function(){
console.log('runrunrun')
}
function Stu(num,name,pets){
Person.call(this,name,pets);//这一句要写在上面防止属性覆盖
this.num = num;
//构造函数
}
//1.构造父类的实例
var p = new Person();
// 2.设置子类的原型对象
Stu.prototype = p;
// 3.修复constructor指针
Stu.prototype.constructor = Stu;
Stu.prototype.run=function(bye){
console.log('我是继承后定义的run')
}
</script>
<script>
var stu = new Stu('001','xiaoming',['maomao','gougou'])
var stu2 = new Stu('002','xiaogang',['momo','gogo'])
stu.run();
stu2.run();
console.log(stu)
console.log(stu2)
</script>
由上面的调用代码我们可以看出子类Stu的实例继承了父类Person的属性和方法,
另外:
<script>
var stu = new Stu('001','xiaoming',['maomao','gougou'])
stu.pets.push('dudu')
var stu2 = new Stu('002','xiaogang',['momo','gogo'])
console.log(stu)
console.log(stu2)

4.寄生组合式继承
我们想到了Object.create(OBJ)创建一个空的对象,让空对象__proto__指向OBJ。 此api存在ie兼容问题,我们可以自己实现,其中一个实现方式为
Object.create = function(obj){
function Fn(){}
Fn.prototype = obj
return new Fn();
}
此方法用图表示为(绿色线部分):

Stu.prototype = Object.create(Person.prototype)
Stu.prototype.constructor = Stu;
完整的代码:
<script>
function Person(name,pets){
this.name = name;
this.pets =pets;
var jj = 'jj'
}
Person.prototype.run = function(){
console.log('runrunrun')
}
function Stu(num,name,pets){
Person.call(this,name,pets);//这一句要写在上面防止属性覆盖
this.num = num;
//构造函数
}
//寄生组合继承
Stu.prototype = Object.create(Person.prototype)
Stu.prototype.constructor = Stu;
//以上方法存在兼容性不兼容ie,我们可以自己写create
Stu.prototype.joke = function(){
console.log('walking')
}
//自己写create
思路: 创建一个空对象,使空对象的__proto__指向obj
<!--Object.create = function(obj){-->
<!-- let oo = {};-->
<!-- oo.__proto__= obj;-->
<!-- return oo;-->
<!--}-->
<!--对于不识别_proto_的情况:-->
<!--Object.create = function(obj){-->
<!-- function Fn(){}-->
<!-- Fn.prototype = obj-->
<!-- return new Fn();-->
<!--}-->
</script>
<script>
var stu = new Stu('001','xiaoming',['maomao','gougou'])
stu.pets.push('dudu')
var stu2 = new Stu('002','xiaogang',['momo','gogo'])
stu.run()
stu2.run()
stu2.joke()
console.log(stu)
console.log(stu2)
</script>