你不知道的JavasScript上篇·第四章·混合对象·类

一、类的理论
1、类的核心概念:多态

  • 是说父类的通用行为可以被子类用更特殊的行为重写

二、类的机制
1、构造函数
类实例是有一个特殊的类方法构造的,这个方法名通常和类名一致;
类构造函数属于类,构造函数大多需要用new来调。
2、类的多态
其实就是子类可以改写父类的同名方法也可以调用继承自父类的同名方法,
任何方法都可以引用继承层次中高层的方法,无论高层的方法名是否相同。
多态的另一个方面是,在继承链的不同层次中一个方法名可以多次被定义,调用方法时会自动选择合适的定义。

多态并不表示子类和父类有关联,子类得到的只是父类的一份副本。
类的继承其实就是复制。

3、混入
模拟类的复制行为,这个方法就是混入。
混入分为两种类型:显示和隐式

  • 显示混入:手动进行复制的。

下面例子中 Person.eat.call(this) 就是显式多态

 function mixin(sourceObj,targetObj){
     for(key in sourceObj){
        console.log(!(key in targetObj))
         //当Person里有,targetObj里没有的时候才进行复制
         if(!(key in targetObj)){
             targetObj[key] = sourceObj[key]
         }
     }
     return targetObj;
 }
 var Person = {
     sex:'person',
     drink:function(){
         console.log('person要喝水')
     },
     eat:function(){
         console.log('person要吃东西')
     }
 }
 var girl = mixin(Person,{
     sex:'girl',
     eat:function(){
         Person.eat.call(this);
         console.log(this.sex+'要吃东西')
     }
 })
 console.log(girl)
 girl.eat();

运行结果如图:

复习上篇内容:

"属性名" in 目标对象:在目标对象上查找属性名也在原型链上也查找
Object.prototype.hasOwnPrototype.call(目标对象,属性名) 只在目标对象上查找属性

这里的
if(!(key in targetObj)){
    targetObj[key] = sourceObj[key]
}
也可以写成
if(!(Objcet.prototype.hasOwnProperty.call(targetObj,key)){
    targetObj[key] = sourceObj[key]
}
但是因为这里targetObj和souceObj并没有继承关系所以不必用Object.prototype.hasOwnProperty.call()
  • 寄生继承
    寄生继承是显式混入模式的一种变体,因为他既是显式的又是隐式的
    实例:
   function Animal(){
       this.type = 'animal'
   }
   Animal.prototype.color = function(){
       console.log("animal's color")
   }
   Animal.prototype.weight = function(){
        this.color();
       console.log("animal's weight")
   }
   function Cat(){
       var cat = new Animal();
       cat.type='cat';
       var anweight = cat.color;
       cat.weight = function(){
           anweight.call(this);
           console.log(this.type+"color" )
       }
       return cat;
   }
   var myCat = new Cat();
   myCat.weight()
  • 隐式混入
    function Something = {
        cool:function(){
            this.greeting = 'hello world';
            this.count = this.count ? this.count+1 : 1 ;
        }
    }
    Something.cool();
    Something.greeting();
    Something.count;
    var  Another = {
        cool:function(){
        //隐式把Something混入Another
            Something.cool.call(this)
        }
    }
    Another.cool();
    Another.greeting;//hello world
    Another.count;//1

这样的结构容易搞不清this,对于方法的引用容易出现问题,一般不从采用这种结构

总结:
类是一种设计模式,也意味着复制。
类被继承时,行为(属性)也会被复制到子类中
多态(在继承链的不同层次名称相同但是功能不同的函数) 看起来似乎是从子类引用父类,但是本质上引用的其实是复制的结果
混入模式可以用来模拟类的复制行为,显式混入实际上无法完全模拟类的复制行为,因为在Js中对象只能复制引用,无法复制被引用的对象或者函数本身(函数也是对象)

posted @ 2019-01-04 16:15  ✔️zhangfl_go  阅读(341)  评论(4编辑  收藏  举报