JS原型链继承
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS原型链继承相关的知识,希望对你有一定的参考价值。
function Parent()
this.name = red;
this.eat = function ()
console.log(走这里了吗)
Parent.prototype.start = function ()
console.log(this.name)
function Children()
Children的原型对象=Parent的原型对象
缺点: 实例对象p指向Parent; 实例对象p不能调用构造函数Parent的方法和属性,只能调用Parent的原型对象的方法和属性
//仅继承了Parent原型对象上的方法和属性
Children.prototype = Parent.prototype
let p = new Children();
console.log(p.name)//undefined
console.log(p.eat)//undefined
console.log(p.start)
//ƒ ()
// console.log(this.name);
//
console.log(p.constructor)
//ƒ Parent()
// this.name = red;
// this.eat = function ()
// console.log(走这里了吗);
// ;
Children.prototype = new Parent()
缺点: 实例对象p指向Parent
Children.prototype = new Parent()//继承了Parent的原型对象prototype的方法和属性以及constructor
let p = new Children();
console.log(p)//Children
console.log(p.name)//red
console.log(p.start)
//ƒ ()
// console.log(this.name);
//
console.log(p.eat)
// ƒ ()
// console.log(走这里了吗);
//
console.log(p.constructor)
// ƒ Parent()
// this.name = red;
// this.eat = function ()
// console.log(走这里了吗);
// ;
//
Children.prototype = new Parent()
Children.prototype.constructor = Children;
Children.prototype = new Parent()//继承了Parent的原型对象prototype的方法和属性以及constructor
Children.prototype.constructor = Children;
let p = new Children();
console.log(p.constructor);
// ƒ Children()
缺点
- 如果父构造函数中含有引用类型的属性,当某个实例改变了该引用类型的属性,则所有实例共享该实例(基本数据类型不会)
- 创建Children实例无法传参
function Parent()
this.name = red;
this.arr = [1, 2, 3];
this.eat = function ()
console.log(走这里了吗)
Parent.prototype.start = function ()
console.log(this.name)
function Children()
Children.prototype = new Parent();
Children.prototype.constructor = Children
let p1 = new Children()
let p2 = new Children()
console.log(p1.arr)
p1.name = blue;
p1.arr.pop();
console.log(p1.name)//blue
console.log(p2.name)//red
console.log(p1.arr)//[2,3]
console.log(p2.arr)//[2,3]
解决缺点一(构造函数继承)
某实例改变父构造函数中引用类型属性的值,所有实例共享修改后的引用类型的属性值
function Parent()
this.arr = [1, 2, 3];
Parent.prototype.start = function ()
function Children()
Parent.apply(this)
//相当于执行了 this.arr = [1, 2, 3];
let p1 = new Children()
let p2 = new Children()
p1.arr.pop()
console.log(p1.arr)//[2,3]
console.log(p2.arr)//[1,2,3]
解决缺点二(构造函数继承)
生成实例时不能传参的问题
function Parent(color,name)
this.color = color;
this.name = name;
this.arr = [1, 2, 3];
this.eat = function ()
console.log(走这里了吗)
Parent.prototype.start = function ()
// console.log(this.name,prototype)
function Children()
console.log(arguments,arguments)
//call传参为多个数值
//apply传值为数组
// Parent.apply(this,arguments)
Parent.call(this,...arguments)
let p1 = new Children()
let p2 = new Children(red,zhangsan)
console.log(p2.color)//red
console.log(p2.name)//zhangsan
console.log(p1.eat===p2.eat)//false
再次出现的问题
我们每次生成实例的时候都会重新生成构造函数的属性和方法
function Children()
//call传参为多个数值
//apply传值为数组
// Parent.apply(this,arguments)
Parent.call(this,...arguments)
解决重新生成实例时生成构造函数的属性和方法(组合继承:原型链继承+构造函数继承)
- 原型链继承:
- 实例改变引用类型的属性,所有实例共享
- 不能传参。
- 构造函数继承:
- 解决了以上原型链的两个问题
- 但是又出现了新的问题,每次生成实例都会重新生成一份构造函数的属性和方法
function Parent(color,name)
this.color = color;
this.name = name;
this.arr = [1, 2, 3];
this.eat = function ()
console.log(走这里了吗)
Parent.prototype.start = function ()
console.log(this.name,prototype)
function Children()
console.log(arguments,arguments)
//call传参为多个数值
//apply传值为数组
// Parent.apply(this,arguments)
// Parent.call(this,...arguments)
// Parent.apply(this,Array.prototype.slice.call(arguments, 1))
Parent.apply(this,[].slice.call(arguments, 1))
Children.prototype = new Parent();
Children.prototype.constructor = Children
let p1 = new Children(1,red,zhangsan)
let p2 = new Children(2,red,zhangsan)
console.log(p1.eat())
console.log(p2.eat())
console.log(p1.start===p2.start) //true
解决了三个痛点:
- 不可传参数
- 多占内存
- 改变引用类型属性,所有实例共享
寄生组合继承(再次出现问题,构造函数调用两次)
1. Parent.call(this,...arguments)
...
2.Children.prototype = new Parent();
以上是关于JS原型链继承的主要内容,如果未能解决你的问题,请参考以下文章