资讯专栏INFORMATION COLUMN

klass 是如何实现JS的类以及类的相关属性和作用

Kross / 1196人阅读

摘要:前面介绍了和是如何实现类,及其类的属性和作用的。今天介绍的就是单纯的实现面向对象的库,只有多行,也照例分析吧。

前面介绍了prototype.jsMootools.js是如何实现类,及其类的属性和作用的。今天介绍的klass.js就是单纯的实现面向对象的库,只有90多行,也照例分析吧。

实现类的步骤

第一步是使用klass新建类,初始化的固定函数是initialize,不能使用其它名称

子类使用ParentClassName.extend{// 子类方法}继承

子类中与父类的同名方法,如果需要在父类的同名方法上拓展,需要在子类的方法体中使用this.supr(args)

如果需要在类的外面增加方法,可以使用methods方法

// 使用 klass 创建类
    var Person = klass({
        // 初始函数固定为 initialize,
        initialize:function(name) {
            this.name = name;
            this.friends = ["jack", "mark"];
        },
        getName: function(){
            console.log("My name is " + this.name);
        },
        setFriends:function(friend){
            this.friends.push(friend);
        },
        getFriends:function(){
            console.log(this.friends)
        }
    });

    // 使用 methods 给类添加方法,子类可以继承该方法
    Person.methods({
        getAge:function(age){
            console.log("My age is " + age);
        }
    })

    // 子类直接通过 ParentClassName.extend 来继承父类
    var Chinese = Person.extend({
        initialize:function(name, addr){
            // 使用 this.supr(args)来使用父类的同名函数
            this.supr(name);
            this.addr = addr;
        },
        getAddr:function(){
            console.log("My address is " + this.addr);
        }
    });

    // 子类直接通过 ParentClassName.extend 来继承父类
    var Japanese = Person.extend({
        initialize:function(name){
            this.supr(name);
        }
    })

    // 实例化类
    var men = new Chinese("allen", "BeiJing");
    men.getName(); // My name is allen
    men.getAge(23); // My age is 23
    men.getAddr(); // My address is BeiJing

    // 以下验证 - 子类继承父类的属性,修改了之后,其他子类再次继承父类,父类的属性的值为何不会改变
    var allen = new Person();
    allen.getFriends(); // ["jack", "mark"]

    var women = new Japanese();
    women.setFriends("lisa");
    women.getFriends(); // ["jack", "mark", "lisa"]

    var men = new Chinese();
    men.setFriends("peter");
    men.getFriends(); //["jack", "mark", "peter"]

    var wallen = new Person();
    wallen.getFriends(); //["jack", "mark"]

JS是如何实现类的方法,有几个重要的问题需要搞清楚

JS是如何创建类的

子类是如何实现继承父类属性和方法的

子类继承父类的属性,修改了之后,其他子类再次继承父类,父类的属性的值为何不会改变

子类和父类的同名函数,在同名函数中使用$supr,是如何做到在子类中共存的
如何实现,不在类中,而是使用methods往类中添加方法的

下面来通过klass.js来具体分析

!function (name, context, definition) {
  if (typeof define == "function") define(definition)
  else if (typeof module != "undefined") module.exports = definition()
  else context[name] = definition()
}("klass", this, function () {
  var context = this
    , f = "function"
      // 是否使用了 supr 来调用父类的同名函数
    , fnTest = /xyz/.test(function () {xyz}) ? /supr/ : /.*/
    , proto = "prototype"

    // o 为创建类时,类的方法
  function klass(o) {
    return extend.call(isFn(o) ? o : function () {}, o, 1)
  }

  // 判断对象是否是函数
  function isFn(o) {
    return typeof o === f
  }

  // 将父类的方法/属性,附加到子类中
  function wrap(k, fn, supr) {
    return function () {
      var tmp = this.supr
        // 当前函数的 supr,就是父类的同名函数
      this.supr = supr[proto][k]
      var undef = {}.fabricatedUndefined
      var ret = undef
      try {
        // this 是当前类,fn 是父类的函数,fn 的上下文是绑定在当前类中,所以就等于父类的方法就继承到子类中了
        ret = fn.apply(this, arguments)
      } finally {
        this.supr = tmp
      }
      return ret
    }
  }

  // 子类继承父类的属性,如果有同名函数,就使用 wrap 方法处理,如果没有,就完全继承该属性
  // what : child; o : parent; supr: parentClass
  function process(what, o, supr) {
    for (var k in o) {
      if (o.hasOwnProperty(k)) {
        what[k] = isFn(o[k])
          && isFn(supr[proto][k])
          && fnTest.test(o[k])
          ? wrap(k, o[k], supr) : o[k]
      }
    }
  }

  // 实现继承的主函数, o创建类时的所有函数,fromSub 为1,不明白为什么不把fromSub设置为true/false
  function extend(o, fromSub) {
    // must redefine noop each time so it doesn"t inherit from previous arbitrary classes
    function noop() {}
    noop[proto] = this[proto]
    var supr = this
      , prototype = new noop()
      , isFunction = isFn(o)
      , _constructor = isFunction ? o : this
      , _methods = isFunction ? {} : o
    function fn() {
      // 如果当前类设置类 initialize 函数,就把传给当前类的参数传递给该函数
      if (this.initialize) this.initialize.apply(this, arguments)
      else {
        // 如果没有设置 initialize ,传入类的参数也能被其它函数使用
        fromSub || isFunction && supr.apply(this, arguments)
        _constructor.apply(this, arguments)
      }
    }

    // 使用 methods 添加方法到当前类,o 为使用 methods 内的方法
    fn.methods = function (o) {
      process(prototype, o, supr)
      fn[proto] = prototype
      return this
    }

    // 指定 fn 的 constructor
    fn.methods.call(fn, _methods).prototype.constructor = fn

    // 使用 ParentClassName.extend 来实现继承时候的
    fn.extend = arguments.callee
      // 使用 implement 来重写父类的方法或者拓展父类的方法
      // o : 函数名 ; optFn : 函数
    fn[proto].implement = fn.statics = function (o, optFn) {
      o = typeof o == "string" ? (function () {
        var obj = {}
        obj[o] = optFn
        return obj
      }()) : o
      // 使用 process 把 implement 中的函数添加到当前类中
      process(this, o, supr)
      return this
    }

    return fn
  }

  return klass
});

JS面向对象系列

《javascript高级程序设计》 继承实现方式

prototype.js 是如何实现JS的类以及类的相关属性和作用

Mootools.js 是如何实现类,以及类的相关属性和作用

总结:prototype.js,Mootools.js和klass.js 实现类的方法的异同与优劣

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84513.html

相关文章

  • prototype.js 如何实现JS的类以及类的相关属性作用

    摘要:实现类的步骤第一步是使用新建类,初始化的固定函数是,不能使用其它名称子类也是使用新建,父类放在第一个参数中,如子类中与父类的同名方法,如果需要在父类的同名方法上拓展,在需要在第一个参数中使用,然后在方法体内使用如果需要在类的外面增加方法,可 实现类的步骤 第一步是使用Class.create新建类,初始化的固定函数是initialize,不能使用其它名称 子类也是使用Class.cr...

    Snailclimb 评论0 收藏0
  • 总结:prototype.js,Mootools.jsklass.js 实现类的方法的异同与优劣

    摘要:构建类的方法使用来构建类使用来构建类使用来构建类继承父类的方法使用子类方法构建子类,继承父类,在与父类同名的方法中,第一个参数为,方法体内使用来拓展父类的同名方法使用正常构建类后,第一个方法使用来继承父类,在子类的方法体中,使用来拓展父类的 构建类的方法 Prototype.js使用Class.create来构建类 Mootools.js使用new Class来构建类 klass.j...

    jeffrey_up 评论0 收藏0
  • Mootools.js 如何实现类,以及类的相关属性作用

    摘要:实现类的步骤第一步是使用新建类,初始化的固定函数是,不能使用其它名称子类也是使用新建,父类在子类中,使用来继承,与子类的方法名,同一级别子类中与父类的同名方法,如果需要在父类的同名方法上拓展,需要在子类的同名方法内,使用如果需要在类的外面增 实现类的步骤 第一步是使用new Class新建类,初始化的固定函数是initialize,不能使用其它名称 子类也是使用new Class新建...

    gitmilk 评论0 收藏0
  • JavaScript MVC 学习笔记(四)类的使用(下)

    摘要:基于函数进行调用的,用来确保函数是在指定的值所在的上下文中调用的。添加私有函数目前上面为类库添加的属性都是公开的,可以被随时修改。以基于的富应用开发为主要学习资料。 控制类库的作用域 在类和实例中都添加proxy函数,可以在事件处理程序之外处理函数的时候保持类的作用域。下面是不用proxy的办法: var Class = function(parent){ var klas...

    Rango 评论0 收藏0
  • JavaScript MVC 学习笔记(三)类的使用(中)

    摘要:实际上,可以将其理解为某种形式的继承。如果上下文是,则使用全局对象代替。例如的第个参数是上下文,后续是实际传入的参数序列中允许更换上下文是为了共享状态,尤其是在事件回调中。 公开记录学习JS MVC,不知道能坚持多久= =。以《基于MVC的JavaScript web富应用开发》为主要学习资料。接上一篇类的学习,发现实在是看晕了,有些例子是能看懂在干嘛,但是不知道为什么这样做,有的甚至...

    DandJ 评论0 收藏0

发表评论

0条评论

Kross

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<