Javascript面对对象篇

/**
 * JavaScript继承:
 *  首先JavaScript是一门基于对象的语言,在ES6之前,JavaScript没有类的概念
 * 为什么说JavaScript是一门基于对象的语言?
 *  很多人都知道OO(Object Oriented)语言都支持接口继承和实现继承,接口继承只继承方法签名,而实现继承则只继承实际的方法,
 *  而JavaScript函数没有签名,也就是没有重载,这也决定了JavaScript在OOP程序设计中,无法实现多态这一特性
 *  在EMCAscript中无法实现接口继承,ECMAScript只支持实现继承,而实现继承则是依靠原型链,其基本核心是利用了原型让一个引用类型
 *  继承另一个引用类型的属性和方法
 * 
 */

// 原型继承
function Person (weight, height) {
  this.weight = weight
  this.height = height
}
Person.prototype = {
  constructor: Person,
  say: function () {
    
  },
  eat: function () {
    
  }
}

function Student (school, address) {
  this.school = school
  this.address = address
}

// 实现继承
Student.prototype = new Person('60', '160')
/**
 * 原型继承的优势:
 *  代码少,可以使用之前对象的全部属性,可以使用它的原型方法
 * 缺陷:
 *  创建继承对象时,其原型对象属性是相同的,需要手动修改
 * 注意问题:
 *  通过原型链继,不能使用对象字面量创建原型方法,这样会重写原型链!
 * 
**/ 
var beautifulGirl = new Student('nanda', '江西')
console.log(beautifulGirl)

// 借用构造函数继承
function Animal (weight, height, type) {
  this.type = type
  this.weight = weight
  this.height = height
}
Animal.prototype = {
  constructor: Animal,
  eat: function () {
    
  }
}
function Dog (dogType, bg) {
  this.dogType = dogType 
  this.bg = bg
  Animal.call(this, '20', '15', '宠物')  // Animal.apply(this, [ ])
}
Dog.prototype = {
  constructor: Dog,
  scratch: function () {
    
  }
}
var myDOg = new Dog('哈士奇', 'black')
console.log(myDOg)
/**
 * 总结:
 *  借用构造函数的缺陷:
 *    不能继承构造函数的原型,他的原型对象(没有进行 new运算),其原型对象依然是自己的原型对象
 *    由于不能达到函数、共有数据复用,导致效率变低,这与构造函数模式类似
 *  本质
 *    其实就是用call和apply实现继承
 **/
// 组合继承
function Tree (treeType) {
  this.treeType = treeType
}
Tree.prototype = {
  constructor: Tree,
  gateway: function () {
    console.log(this.treeType)
  }
}
function Willow (height, year, size) {
  this.height = height
  this.year = year
  this.size = size
  Tree.call(this)
} 

Willow.prototype = new Tree()
var willowObj = new Willow(170, 12, 15)
console.log(willowObj)
/**
 *  优势:
 *    即可以解属性问题,又可以解决方法问题;
 *  缺陷:代码增加, 无论什么情况下都会调用两次超类型函数,一次是实现子类型原型继承的时候,一次实现
 *    是子类型的构造函数内部,继承实例时,虽然子类型能够最终包含超类型的所有原型,但是,不得不
 *    通过子类型中的实例属性属性的更新
 * 
 **/
 // 寄生继承
function object (original) {
  function F () {
  } 
  F.prototype = original // 构造函数 -> original的构造函数
   // 实例化对象    
  return new F()
}
// 得到返回的实例
function createAnother (original) {
  var clone = object(original)
  // 增强对象时无法共享方法
  clone.prototype.sayName = function () {
    alert('android Stdudio')
  }
  return clone
}

/**
 * 1、使用寄生式继承的思路和工程模式有类似,即创建一个仅仅用来封装的函数,该函数在内部以某种
 *  方式去增强对象,最后返回一个实例,original是当前的原型对象
 *  缺点:
 *    使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率
 **/

// 组合寄生继承
function object (original) {
  function F (){}
  F.prototype = original // F.prototype.constructor -> original.prototype
  return new F()
}
function SuperType (age) {
  this.age = age
}
function SubType () {
  SuperType.call(this, 10)
}
// superType为父类,SubType为子类
function inheritPrototype (subType, superType) {
  var prototype = object(superType.prototype)
  prototype.constructor = subType  // 此时, 弥补因为重写原型丢失构造属性
  subType.prototype = prototype
}
var subObj = new SubType(20)
/**
 * 无疑,组合继承时JavaScript常用的继承方式之一,但是之前说了他的缺点,需要调用两次函数和更新
 * 属性,所以寄生组合寄生便完善了这点,使之成为目前最为标准和流行的继承方式
 * 
 **/

// 继承的总结:
/**
 *  1、在ES6之前,js没有类的概念,js实现继承依靠原型链,在OOP中,js只能实现继承和封装,不能实现多态,因为JavaScript没有函数签名
 *  2、js的原型链
 *    每个构造函数中都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例对象包含一个指向原型对象的
 *    内部指针,JavaScript继承核心就是让原型对象等于一个类型的实例,那么此时的原型对象将包含着一个指向另一个原型
 *    的指针,相应的,另一个原型对象也是另一个类型的实例,通过这样的层层递进,就构成了实例与原型的链条!
 *    最终有构造函数的事情吗? 在原型链中并没有构造函数的参与!
 * 3、默认的原型
 *    记住!所有的原型对象都继承自Object,而这个继承也是通过原型链式实现的,这也是为什么所有自定义方法都具有toString、valueOf、
 * 4、继承的优点:
 *    节省内存,实现OOP的编程模式,共享数据
 */
 
 // 运用继承进行的数据共享
 function Animate (name, age, sex) {
   this.r = name
   this.a = age
   this.c = sex
 }
 
 // 如果你的对象原型继承了其他原型,你最好不要这样做,这样你将重写原型链
 Animate.prototype = {
   constructor: Animal,
   arr: []
 }
 var objOne = new Animal('dog', 6, 1)
 var objTwo = new Animal('zu', 1, 0)
 objOne.arr.push(this.name)
 objTwo.arr.push(this.age.toString())
 
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值