JavaScript 对象的创建与继承——继承篇

继承篇

原型链继承

当我访问一个对象实例的属性时候,这个就会在实例的本身找是否存在这个属性,如果没有则访问[__proto__]或者prototype
在这里插入图片描述
所以,如果我们需要实现继承,可以通过修改构造函数的原型来实现,这样每一个实例都可以得到父类的属性和方法。
我们直接代码来看下如何实现吧!

var Father = function(age) {
	this.name = 'father'
	this.age = age
}
var Son = function (){
	
}
Son.prototype = new Father()
Son.prototype.returnFather= function(){
	console.log(this.name,this.age)
}
var son1 = new Son('53')
son1.returnFather()

输出

father undefined

这里undefined是因为father实例没有一个构造函数constructor的指针,所以new的时候没有指向到father的构造函数
在这里插入图片描述
我们通过代码来验证下原型的关系

var Father = function(age) {
	this.name = 'father'
	this.age = age
}
var Son = function (){
	
}
var _f = new Father()
Son.prototype = _f
Son.prototype.returnFather= function(){
	console.log(this.name,this.age)
}
var son1 = new Son('53')
son1.returnFather()
console.log(son1.__proto__== _f) // true
console.log(Father.prototype== _f.__proto__)// true

借用构造函数继承

我们前面了解new的过程就是绑定一个对象作用域并且指向构造函数返回对象,就可以获取到构造函数里面的属性和方法。
我们同样可以将父类的构造函数进行手动的绑定作用域,并且执行。这样在new子类的时候就可以类似同时在new父类的构造函数一样。

var Father = function(age) {
   this.name = 'father'
   this.age = age
}
var Son = function (age){
   Father.call(this,age)
}

var son1 = new Son('53')
console.log(son1.age) // 53

var son2 = new Son('32')
console.log(son2.age) // 32

在这里插入图片描述

组合式继承

结合构造函数和原型,我们需要将共享的方法和属性通过原型继承,而除此之外,我们需要对构造函数调用父类的构造函数继承实例的属性和方法。

var Father = function(age) {
   this.name = 'father'
   this.age = age
}
var Son = function (age){
   Father.call(this,age)
}
Son.prototype = new Father()
Son.prototype.constructor = Son
Son.prototype.returnName = function() {
   return this.name
}

var son2 = new Son('32')
console.log(son2.age,son2.returnName())

Son.prototype.constructor = Son重要的是这一步,因为你修改了原本Sonprototype,因为new调用的构造函数constructor是保存到原型上的,所以你需要手动的添加到原型上。
还有一个需要注意,因为这种方法的函数需要自己另外添加,因为你如果写进Father的构造函数,这样每个实例都会存在一份这个函数的变量。

原型式继承

var creatObject = function (o) {
	var obj = function(){}
	obj.prototype = o
	return new o()
}

这个看起来非常熟悉,其实就是我们object.create的方法
在这里插入图片描述
创造的实例的prototype就是父类,这个缺点就导致了父类所有属性和方法都是共用的。
我们可以将这些额外需要添加的封装到一个方法里,这样就是寄生式继承

寄生式继承(工厂模式)

function create (father) {
	var clone = Object.create(father)
	clone.sayName = function(){console.log(this.name)}
	return clone
}

寄生式组合继承

我们组合继承有一个问题就是构造函数放的是属性,而父类原型放的是方法,通过构造函数继承属性,通过原型链继承方法。

 var Father = function(age) {
	this.name = 'father'
	this.age = age
}
var Son = function (age){
	Father.call(this,age)
}
function create(son,father){
	var prototype = Object.create(father.prototype)
	son.prototype = prototype
	son.prototype.constructor = son
}
var obj = create(Son,Father)
// obj的prototype指向的是父类的prototype,所以只需要往父类prototype的添加方法即可

在这里插入图片描述

ES6进化篇

ES6的class

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}
  • constructor构造函数,存放属性
  • 其他直接设置为原型的方法,不用添加function
    等价于ES5的写法
var Point = function (x,y){
    this.x = x;
    this.y = y;
}
Point.prototype.toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
  • 静态方法/属性
class Point {
}
Point.test = function(){console.log(1)}
Point.prop = 1;
var p = new Point()
p.test()// 报错
p.prop //undefined
  • 除了在构造函数添加实例属性,我们也可以尝试使用其他方法
class Point {
	  constructor() {
	    this._count = 0;
	  }
	get Value(){
		return this._count;
	}
}
var p = new Point()
console.log(p.value)// 0

ES6的继承

  • 规则使用extends进行继承
  • 子类构造函数开头一定需要携带super(); // 调用父类的constructor()
class Point { /* ... */ }
class ColorPoint extends Point {
  constructor() {
  	super()
  }
}
let cp = new ColorPoint(); 
判断父子类关系

Object.getPrototypeOf(ColorPoint) === Point //true

class中的prototype和__proto__

(1)子类的__proto__属性,表示构造函数的继承,总是指向父类。

(2)子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值