这里记录一下原型和原型链的理解
构造函数 原型对象 对象原型
构造函数里有一个对象prototype就是原型,构造函数实例化new出来一个实例对象,每个实例对象都有一个__proto__,这个__proto__指向构造函数的prototype原型,实例对象和构造函数的prototype原型都有一个constructor指向构造函数。构造函数的prototype原型也有个__proto__指向Object的prototype。
function Father() {
this.color = 'red'
this.name = 'lv'
}
const Foo = new Father
console.log(Foo.__proto__ === Father.prototype) //true
console.log(Foo.__proto__.__proto__ === Object.prototype) //true
有关constructor
如果是给原型对象往里加属性,不会改变原型对象constructor指到构造函数上。如果是重新写了原型对象,会影响原型对象,导致没有constructor指到构造函数上。
//这是给原型对象往里加属性,不会改变原型对象constructor指到构造函数上
Father.prototype.year = function () {
this.year = 18
}
//这是重新写了原型对象,会影响原型对象,导致没有constructor指到构造函数上
Father.prototype = {
age:18,
fn:function(){
console.log('22222')
}
}
//这里的不管原型对象还是实例对象的constructor都找不到构造函数身上
console.log(Father.prototype.constructor === Father) //false
console.log(Foo.constructor === Father) //false
//所以这里要把构造函数的原型对象的constructor指到构造函数上
Father.prototype.constructor = Father
//或者在这里加上constructor:Father
/* Father.prototype = {
age:18,
fn:function(){
console.log('22222')
},
constructor:Father
} */
console.log(Father.prototype.constructor === Father) //true
console.log(Foo.constructor === Father) //true
原型继承方法
原型链继承
就是把子类实例对象能访问的的prototype等于父类的实例对象,就能访问Father.prototype
function Father() {
this.color = 'red'
this.name = 'lv'
this.arr = [1, 2, 3, 4]
}
Father.prototype.getName = function () {
console.log(this.name)
}
function Son() {
}
//将父类的实例赋给子类的原型
//这是原型链继承 就是把子类实例对象能访问的的prototype等于父类的实例对象,就能访问 Father.prototype
Son.prototype = new Father()
//son和son1本来不相关 son.arr.push(5)时son1.arr也变了,引用值共享的问题
var son = new Son()
var son1 = new Son()
son.arr.push(5)
console.log(son.arr) //[1, 2, 3, 4, 5]
console.log(son1.arr) //[1, 2, 3, 4, 5]
缺点:引用值共享的问题
构造函数继承
可以解决原型链继承的引用值共享的问题,但是父类的Father.prototype.getName里的方法拿不到
//构造函数继承Father.call(this)
function Son() {
Father.call(this)
}
var son = new Son()
var son1 = new Son()
son.arr.push(5)
console.log(son.arr) //[1, 2, 3, 4, 5]
console.log(son1.arr) //[1, 2, 3, 4]
组合继承(伪经典继承)
调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)
//构造函数继承Father.call(this)
function Son() {
Father.call(this)
}
//将父类的实例赋给子类的原型
//原型链继承
Son.prototype = new Father()
var son = new Son()
var son1 = new Son()
son.arr.push(5)
console.log(son.arr) //[1, 2, 3, 4, 5]
console.log(son1.arr) //[1, 2, 3, 4]
console.log(son.getName) //fn{}
寄生继承(经典继承)
Object.create()方法创建一个新对象Father.prototype,创建一个对象,对象的原型为creat()参数,就是指定当前对象的原型为传入的参数。
//构造函数继承Father.call(this)
function Son() {
Father.call(this)
}
//将父类的实例赋给子类的原型
//原型链继承
Son.prototype = Object.create(Father.prototype)
Son.prototype.constructor = Son
var son = new Son()
var son1 = new Son()
son.arr.push(5)
console.log(son.arr) //[1, 2, 3, 4, 5]
console.log(son1.arr) //[1, 2, 3, 4]
console.log(son.getName) //fn{}
//Object.create源码
Object.create = function (o) {
var F = function () {};
F.prototype = o;
return new F();
}
class继承(ES6新增)
extends继承,super方法
class farther {
constructor(sonname) {
this.sonname = sonname
}
say() {
console.log('你的姓是' + this.sonname)
}
}
// extends方法
class son extends farther { }
let yours = new son('wang')
yours.say()
class son extends farther {
constructor(sonname, grandsonname) {
super(sonname, grandsonname)
this.sonname = sonname
this.grandsonname = grandsonname
}
sayson() {
console.log('儿子的姓是' + this.grandsonname)
}
}
const sons = new son('lv', 'w')
const grandsons = new son('lv', 'w')
sons.say()
grandsons.sayson()