资讯专栏INFORMATION COLUMN

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

gitmilk / 1595人阅读

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

实现类的步骤

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

子类也是使用new Class新建,父类在子类中,使用Extends:parentClass来继承,Extends与子类的方法名,同一级别

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

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

// 使用 Class.create 创建类
    var Person = new Class({
        // 初始函数固定为 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)
        }
    });

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

    // 子类通过 new Class 创建类
    var Chinese = new Class({
        // 子类通过 Extends 来继承父类
        Extends:Person,
        initialize:function(name, addr){
            this.parent(name);
            this.addr = addr;
        },
        getAddr:function(){
            console.log("My address is " + this.addr);
        }
    });

    var Japanese = new Class({
        Extends:Person,
        initialize:function(name){
            this.parent(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是如何创建类的

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

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

子类和父类的同名函数,使用this.parent(args)在函数中使用,是如何做到在子类中的同名函数共存的

如何实现,不在类中,而是使用implement往类中添加方法的

下面来通过Mootools.jsclass来具体分析

(function(){

    // 新建一个 Class 的类,new Type 也是一个函数
var Class = this.Class = new Type("Class", function(params){
    // 如果传入的 参数是方法,就把该函数当作初始化的方法
    if (instanceOf(params, Function)) params = {initialize: params};

    var newClass = function(){
        // 解除属性里对其他对象的引用
        reset(this);
        // 如果当前类正在构建,就返回当前类,不做任何操作
        if (newClass.$prototyping) return this;
        // $caller 和 $family 是什么啊
        this.$caller = null;
        this.$family = null;
        // 有初始化函数的话,就传入参数到该初始化函数,没有就返回自身
        var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
        // 这句又是什么意思,一个 $caller ,一个 caller
        this.$caller = this.caller = null;
        return value;
        // extend(this) 把类的方法,都添加到当前新建的类中
        // implement(params) 把 params 的所有方法都添加到当前类中
    }.extend(this).implement(params);

    //指定 constructor ,以便使用 instanceOf 来验证
    newClass.$constructor = Class;
    newClass.prototype.$constructor = newClass;
    // 指定当前类的父类是哪一个
    newClass.prototype.parent = parent;

    return newClass;
});

/*
    在子类拥有和父类同名方法时,使用 this.parent(args) 方法来调用父类的该方法
 */
var parent = function(){
    // :: 如果当前方法没有被调用,那么就说,parent 方法没有被调用
    if (!this.$caller) throw new Error("The method "parent" cannot be called.");
    // 当前函数被调用的名字 function person(age) { this.age = age },则 age 被调用的就是 person 函数,就是得到 person 这个名字
    var name = this.$caller.$name,
        // $owner 当前类对象, 得到当前类对象的父类对象
        parent = this.$caller.$owner.parent,
        // 得到父类相同名字的方法
        previous = (parent) ? parent.prototype[name] : null;
    if (!previous) throw new Error("The method "" + name + "" has no parent.");
    // 父类的该同名函数,添加到当前子类中
    return previous.apply(this, arguments);
};

// 解除属性里对其他对象的引用
// 这个解除的例子,可以看 http://hmking.blog.51cto.com/3135992/675856
var reset = function(object){
    for (var key in object){
        var value = object[key];
        switch (typeOf(value)){
            case "object":
                var F = function(){};
                F.prototype = value;
                object[key] = reset(new F);
                break;
            case "array": object[key] = value.clone(); break;
        }
    }
    return object;
};

var wrap = function(self, key, method){
    if (method.$origin) method = method.$origin;
    var wrapper = function(){
        // 如果方法是是被保护的,或者这个方法没有 caller ,就不能被调用
        if (method.$protected && this.$caller == null) throw new Error("The method "" + key + "" cannot be called.");
        var caller = this.caller, current = this.$caller;
        this.caller = current; this.$caller = wrapper;
        // 将 method 绑定到当前对象中
        var result = method.apply(this, arguments);
        this.$caller = current; this.caller = caller;
        return result;
        // 通过extend ,把当前函数的属性附加到 self 里去
    }.extend({$owner: self, $origin: method, $name: key});
    return wrapper;
};

var implement = function(key, value, retain){
    //  Mutators 的 key 只有 Extends 和 Implements
    if (Class.Mutators.hasOwnProperty(key)){
        value = Class.Mutators[key].call(this, value);
        if (value == null) return this;
    }

    if (typeOf(value) == "function"){
        // 隐藏的方法子类就不要再继承使用了
        // $hidden 和 $protected 去看函数那章
        if (value.$hidden) return this;
        this.prototype[key] = (retain) ? value : wrap(this, key, value);
    } else {
        // merge 应该是同名的函数,这样就直接添加进去就好
        Object.merge(this.prototype, key, value);
    }

    return this;
};

// 为了将父类的的属性继承到子类,会使用中间变量,将父类传递给中间变量,再通过中间变量传递给子类
var getInstance = function(klass){
    // 谁知当前当前类正在构建
    klass.$prototyping = true;

    var proto = new klass;
    // 这里就删除 $prototyping ,也就是构建的过程就是上面这一行咯
    delete klass.$prototyping;
    return proto;
};

// 这里有 overloadSetter ,所以,可能是 Class.implement 方法,来给类额外添加函数的
Class.implement("implement", implement.overloadSetter());

Class.Mutators = {

    // 传给 extends 的参数是 parent
    Extends: function(parent){
        // 指向当前类的父类是 parent 参数
        this.parent = parent;
        // 使用 getInstance 得到父类的全部方法
        this.prototype = getInstance(parent);
    },

    Implements: function(items){
        Array.convert(items).each(function(item){
            var instance = new item;
            for (var key in instance) implement.call(this, key, instance[key], true);
        }, this);
    }
};

})();
/*
 Extends 其实是分两部分,使用 Extends 的时候,是把父类的所有属性和方法,通过 getInstance 来附加到当前类中
 然后当前类的方法中,可以使用 this.parent(args) 方法,来把父类的同名方法加载进来

 Implements 方法中没有指代 this.parent = parent ,所以如果当前类写了和父类同名的方法,就会覆盖父类的方法
 Implements 只是给当前类添加更多的方法
 */

JS面向对象系列

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

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

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

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

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

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

相关文章

  • 总结:prototype.jsMootools.jsklass.js 实现的方法的异同与优劣

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

    jeffrey_up 评论0 收藏0
  • klass 如何实现JS以及相关属性作用

    摘要:前面介绍了和是如何实现类,及其类的属性和作用的。今天介绍的就是单纯的实现面向对象的库,只有多行,也照例分析吧。 前面介绍了prototype.js和Mootools.js是如何实现类,及其类的属性和作用的。今天介绍的klass.js就是单纯的实现面向对象的库,只有90多行,也照例分析吧。 实现类的步骤 第一步是使用klass新建类,初始化的固定函数是initialize,不能使用其它...

    Kross 评论0 收藏0
  • prototype.js 如何实现JS以及相关属性作用

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

    Snailclimb 评论0 收藏0
  • 《javascript高级程序设计》 继承实现方式

    摘要:寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部已某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象。 这篇本来应该是作为写JS 面向对象的前奏,只是作为《javascript高级程序设计》继承一章的笔记 原型链 code 实现 function SuperType() { this.colors = [red,blu...

    cppprimer 评论0 收藏0
  • 【程序员必备】知识点 持续更新

    TCP/IP HTTP和HTTPS有何区别? httpbin 一个简单的HTTP请求和响应服务。 TCP的三次握手与四次挥手 通俗易懂版,详细版本 MySQL CHAR和VARCHAR存取的差别 《高性能MySQL》笔记 - MySQL 锁的基本类型 MySQL中的锁之一:锁的必要性及分类 MySQL中的锁之二:行锁、页锁、表锁 MySQL Like与Regexp的区别 数据结构 数...

    hellowoody 评论0 收藏0

发表评论

0条评论

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