关于javascript 的继承

一.继承的几种方法

// 假设有一个需要继承的一个类型 Animal

function Cat() {}
Cat.prototype = new Animal
// 添加一个属性
Cat.prototype.name = 'cat'
```

* 构造继承

```
// 假设有一个需要继承的一个类型 Animal

function Cat(name){
Animal.call(this)
// 添加一个属性
this.name = name || 'cat'
}
```

* 所以组合这两个东东:组合继承

```
// 假设有一个需要继承的一个类型 Animal

function Cat(name) {
Animal.call(this)
// 添加属性
this.name = name || 'cat'
}
Cat.prototype = new Animal()
// 添加方法
Cat.prototype.say = function () {
// TOOD
}
```

* 优化内存节省一些:

```
// 假设有一个需要继承的一个类型 Animal

function Cat(){
Animal.call(this)
this.name = 'cat'
}

(function(){
// 创建一个没有实例方法的类
var Super = function () {}
Super.prototype = Animal.prototype
// 将实例作为子类的原型
Cat.prototype = new Super()
// 添加方法
Cat.prototype.say = function () {
// TOOD
}
})()

二.根据场景使用继承

有两个对象,格式如下,请根据后续条件补充代码

 

1  function Base() {
2  }
3   Base.extend = function(){
4  }

前置条件: 

  

var Base = require('之前的两个对象的路径')
var View = Base.extend()

 

要满足以下条件:

1.可以继承

var MyClass = Base.extend({
        getVal: function () {
          return 'hello world'
        }
      }, {
        say: function (word) {
          return word
        }
      }) //Base.extend 传了两个json对象
    var myclass = new MyClass

      assert.equal(myclass.getVal(), 'hello world') //MyClass实例拥有getVal方法,说明getVal的方法是个prototype上的方法 
      assert.equal(MyClass.say('haha'), 'haha')//MyClass自己的方法,静态方法
      assert.equal(myclass instanceof MyClass, true)
      assert.equal(myclass instanceof Base, true) //myclass继承Base

2.可以继承多次

 it('可以extend多次', function () {
      var A = Base.extend({
        say: function (word) {
          return word
        }
      })
      var B = A.extend()  //继承了Base.extend 的 extend 方法
      var b = new B
      assert.equal(b.say('hello world'), 'hello world') //
      assert.equal(b instanceof View, false)            //不是继承View,说明是在Base.extend 中重新定义了一个新类型
      assert.equal(b instanceof B, true)                //
      assert.equal(b instanceof A, true)                // 
      assert.equal(b instanceof Base, true)             //继承了Base
    })

3.能够监听事件

 it('能够监听事件', function (done) {
      const view = new View
      view.on('test', function () {//Base.extend 的 prototype 有一个方法是 on
        done()
      })
      view.trigger('test')//Base.extend 的prototype有一个方法是trigger,trigger 触发 on 中绑定的对应名称的 function
    })

 

4.能够监听事件并传值

   it('能够监听事件并传值', function (done) {
      const view = new View
      view.on('test', function (value) {  
        assert.equal(value, 'hello world')
        done()
      })
      view.trigger('test', 'hello world')//传值前面的没有传值可以使用arguments
    })

 

5.监听函数的this指向自己]

 

 

it('监听函数的this指向自己', function (done) {
      const view = new View
      view.on('test', function () {//on函数绑定的this是父对象View
        assert.equal(this, view)
        done()
      })
      view.trigger('test')
    })

 

 6.补充代码
  根据以上分析:

  1.       on和trigger 可以绑定到Base 的 prototype上
  2.       Base.extend 返回一个新的类型Cur
  3.       新的类型Cur继承Base.extend  
    function Cat(){
    Animal.call(this)
    this.name = 'cat'
    }
    
    (function(){
    // 创建一个没有实例方法的类
    var Super = function () {}
    Super.prototype = Animal.prototype
    // 将实例作为子类的原型
    Cat.prototype = new Super()
    // 添加方法
    Cat.prototype.say = function () {
    // TOOD
    }
    })()
  4.       Base.extend传递的第一个对象的属性 绑定到 Cur 的 prototype 上
  5.       Base.extend 传递的第二个对象的属性  绑定到 Cur上
  6.       Base.extend 属于自己的属性(实现继承多次的属性extend)  绑定 到 Cur 上
完整代码

function Base(){
  this.events = {}
}


Base.prototype.on = function(key,fn){
  this.events[key] = fn;
}


Base.prototype.trigger = function(key)
{
  var slice = [].slice
  var args = slice.call(arguments,1)
  this.events[key].apply(this,args);
}


Base.extend = function(prop,static)
{
  var Super = this;


  function Cur()
   {
     Super.call(this);
   }


    function Pile() {}
   Pile.prototype = Super.prototype
    Cur.prototype = new Pile();


   for(var p in prop)
  {
    Cur.prototype[p] = prop[p];
  }


  for(var p in Super)
 {
   Cur[p] = Super[p];
 }

 for(var p in static)
 {
  Cur[p] = static[p];
 }


  return Cur;
}


module.exports = Base

 

优化下代码: 

 var slice = [].slice

function merge(target) {
    //delete the first argument
    var srcs = slice.call(arguments, 1)
    srcs.forEach(function (src) {
        for (var key in src) {
            // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
            if (src.hasOwnProperty(key)) {
                target[key] = src[key]
            }
        }
    })
}

function Base() {
    this.events = {}
}
Base.extend = function (proto, static) {

    var Super = this;
    function Cur() {
        Super.call(this)
    }
    var Pile = function () {}
    Pile.prototype = Super.prototype
    Cur.prototype = new Pile()

    merge(Cur.prototype, proto)
    merge(Cur, Super,static);
    return Cur
}
merge(Base.prototype, {
    on: function (event, fn) {
        (this.events[event] = this.events[event] || [])
            .push(fn)
    },
    trigger: function (event) {
        var args = slice.call(arguments, 1)
        ;(this.events[event] || [])
            .forEach((fn) => {
                fn.apply(this, args)
            })
    }
})

module.exports = Base

 

posted on 2018-02-11 15:13  michelle_phone  阅读(126)  评论(0编辑  收藏  举报