JavaScript中的继承!

有继承,必定会有两个构造函数,一个是父类,一个是子类,只有这样才能发生继承关系。话不多说直接进入主题。
这里先声明一个父类Person, 下面的继承均继承于这里的Person父类。

function Person(name){
	this.name = name || 'person'
	this.eat = function(){
		console.log('this is eat');
	}
}
Person.prototype.sayHi = function(){
	console.log('this is sayHi');
}

1. 原型继承

依据每个对象都有一个__proto__属性, 所有继承的都通过原型链来查找
new Person 会打印出

{
   name: 'person',
   eat: function () {},
   __proto__: {
     constructor: Person,
     sayHi: function () {},
     __proto__: Object
   }
}

当我们新创建一个构造函数Student

function Student(){
	
}

Student.prototype = new Person
var s = new Student
打印结果为  
{
	__proto__: {
		name: 'Person',
		eat: function(){}
		__proto__:{
			 constructor: Person,
             sayHi: function () {},
             __proto__: Object
		}
	}
}

3. 借用构造函数继承

主要是通过call方法来改变this指向实现的。

function Student(name) {
    // 在这里执行 Person 这个函数内部的所有代码
    // 并且吧代码中的 this 改变成 指向 s
    Person.call(this)
}
var s = new Student
console.log(s);

缺陷: 没有继承父类的原型的属性和方法
打印出结果为:

{
     name: 'person',
      eat: function () {},
      __proto__: {
        constructor: Student,
        __proto__: Object
      }
}

3. 组合继承

是将原型继承和借用构造函数继承相结合的方法。
这样会重复父类的私有属性

function Student (){
	Person.call(this)
}
Student.prototype = new Person
var s = new Student

打印结果为
 {
    name: 'person',
     eat: function () {},
     __proto__: {
       name: 'person',
       eat: function () {},
       __proto__: {
         constructor: Person,
         sayHi: function () {},
         __proto__: Object
      }
   }
}

4. 拷贝继承

主要使用了for in 遍历式的对象,
使用方法:
在构造函数中使用new Person
把父类遍历到构造函数的原型中

function Student(){
	var p = new Person
	for(var key in p){
		Student.prototype[key] = p[key]
	}
}
var s = Student

结果为
 {
    __proto__: {
       constructor: Student,
       name: 'person',
       eat: function () {},
       sayHi: function () {},
       __proto__: Object
     }
}

for in 对性能的消耗比较高

5. 寄生式继承

主要使用了return 方法, 结束函数执行并返回函数结果
使用: return一个new Person

function Student(){
	this.abc = "abc"
	var p = new Person
	return p
}
Student.prototype.fn = function(){}
var s = new Student

打印结果为
{
	__proto__:{
		name: 'person',
		eat: function (){}
		__proto__:{
			constructor: Person,
			say: function(){}
			__proto__: Object
		}
	}
}

这样自己的私有属性和原型都没有了

6. 寄生式继承1

主要使用了借用构造函数继承和寄生式继承

function Student(){
	Person.call(this) // 不能继承父类的原型
}
Student.prototype = Person.prototype
Student.prototype.fn = function(){}
var s = new Student

结果为
 {
    name: 'person',
     eat: function () {},
     __proto__: {
       constructor: Person,
       sayHi: function () {},
       __proto__: Object
     }
}

这样看似是操作的Student,实际上是操作的父类,这里添加的fn方法,父类中也会出现

7. 寄生式继承2

主要使用了组合 构造函数和寄生式继承

 function Student(name) {
      Person.call(this)  // 没有继承父类的原型属性和方法
 }

 // Abc 没有私有属性
 (function () {
   function Abc() {
     // this.constructor = Student
   }
   Abc.prototype = Person.prototype
   Student.prototype = new Abc
 })()
 Student.prototype.constructor = Student
 Student.prototype.fn = function () {}

 var s = new Student

缺陷
书写复杂
当我不需要操作 自己的 prototype 的时候,多出来的那一个东西
就是在我们的原型链上多加了一个环节
属性或者方法获取的时候,原型链查找机制会多消耗了一次性能

8. 淼式继承法

在借用构造函数的基础上
使用拷贝继承,但是拷贝的不是 new Person,而是直接拷贝 Perosn.prototype

 function Student(name) {
     Person.call(this)
   }

/*
自执行函数
()()
!function () {}
~function () {}
*/

~function () {
    var obj = Person.prototype
    for (var key in obj) {
      Student.prototype[key] = obj[key]
	}
}
Student.prototype.fn = function () {}
   
var s = new Student

但是使用了for in循环,会增加性能消耗

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值