文档章节

MooTools Class 使用、继承详解(下)

DerekLi
 DerekLi
发布于 2014/05/09 09:45
字数 1769
阅读 107
收藏 0
点赞 16
评论 3

    继承

        继承的主要好处表现在代码的重用方面,通过建立类之间的继承关系,有些方法我们只需要定义一次就可以了。同样,如果需要修改这些方法或排查其中的错误,那么由于其定义只出现在一个位置,所以非常有利于节省时间和精力。MooTools实现类的继承有两种模式:原型式继承和多亲继承,原型式继承由内建的Extends Mutator来实现,多亲继承由Implements Mutator或implement方法来实现。

        原型式继承这里就不多讲了,着重讲一下多亲继承。在JavaScript里,因为一个对象只能拥有一个原型对象,所以不允许子类继承多个超类,不过我们可以利用多个掺元类(minix class)或掺元对象对一个类进行扩充,这样类的实例就可以拥有mixin类(对象)中的方法、属性,所以这实际上实现了多继承的效果。通常mixin类(对象)包含一些通用的方法,大家可以看看MooTools里Class.Extras模块中三个mixin类的定义(Chain、Events、Options)。

        这里还需要注意的的一点是,在派生具有私有成员的的类或implement mixin类(对象)时,因为在父类(或mixin)中访问这些私有变量的方法是公有的,所以他们也会被遗传下来。所以子类可以间接访问父类(或mixin)的私有成员,但子类自身的实例方法都不能直接访问这些私有属性,而且你也不能在子类中添加能够直接访问他们的方法(作用域变量,你想访问也访问不了啦,呵呵)。

        首先我们先建立一个基类:

var Animal = new Class({  
    initialize: function(age){  
        this.age = age;  
    }  
});

        使用Extends Mutator派生一个子类:

var Cat = new Class({  
    Extends: Animal,  
    initialize: function(name,age){  
        this.parent(age);  
        //callsinitalizemethodofAnimalclass  
        this.name = name;  
    }  
});  
var cat = new Cat('Micia',20);  
console.log(cat.name); //'Micia'  
console.log(cat.age);//20

        利用Implements Mutator扩充一个类,首先建立一个mixin类:

var Mixin = new Class({  
    getName: function(){  
        return this.name;  
    },  
    setName: function(value){  
        this.name = value  
    }  
});  
var Cat = new Class({  
    Extends: Animal,  
    Implements: Mixin,  
    initialize: function(name,age){  
        this.parent(age);  
        //callsinitalizemethodofAnimalclass  
        this.name = name;  
    }  
});  
var cat = new Cat('Micia',20);  
console.log(cat.name); //'Micia'  
console.log(cat.age); //20  
  
cat.setName('Dog');  
console.log(cat.getName()); //'Dog'

        使用implement方法扩充一个类,首先家里一个mixin对象:

//mixin对象存储一些通用方法,可以被不同的类implement  
var objMixin = (function(){  
    var counter = 0;  
    return {  
        init: function(){  
            counter + = 1;  
        },  
        getCounter: function(){  
            return counter;  
        },  
        getAge: function(){  
            return this.age;  
        },  
        setAge: function(value){  
            this.age = value;  
        }  
    };  
})();  
var Cat = new Class({  
    Extends: Animal,  
    Implements: Mixin,  
    initialize: function(name,age){  
        this.parent(age);  
        //callsinitalizemethodofAnimalclass  
        this.name = name;  
    }  
});  
Cat.implement(objMixin);  
var Dog = new Class({  
    Extends: Animal,  
    Implements: Mixin,  
    initialize: function(name,age){  
        this.parent(age);  
        //callsinitalizemethodofAnimalclass  
        this.name = name;  
    }  
});  
Dog.implement(objMixin);  
var cat = new Cat('Micia',20);  
console.log(cat.name); //'Micia'  
console.log(cat.age); //20  
  
cat.setName('汤姆');  
console.log(cat.getName()); //'汤姆'  
  
cat.setAge(12);  
console.log(cat.getAge()); //12  
  
//对mixin对象的私有属性进行操作  
cat.init();  
console.log(cat.getCounter());//1  
  
var dog = new Dog('小狗',6);  
console.log(dog.name); //'小狗'  
console.log(dog.age); //6  
dog.setName('布鲁托');  
console.log(dog.getName());//'布鲁托'  
  
dog.setAge(8);  
console.log(cat.getAge());//8  
  
//对mixin对象的私有属性进行操作  
dog.init();  
console.log(dog.getCounter()); //2  
console.log(cat.getCounter());//2

        大家都看明白了吧,呵呵,不过通过上面的代码我们引申出另外一个问题,注意上面的Cat类的设计,我们首先设计了Extends,然后是Implements,再就是Cat类本身的方法属性,MooTools内部对Class构造函数解析时是按照我们设计时的顺序解析的吗?答案是按照我们设计时的顺序解释的。简单来讲MooTools通过for-in对对象进行枚举来遍历每个成员进行解释的,等等......那个ECMAScript最新版对for-in语句的遍历机制又做了调整,属性遍历的顺序是没有被规定的,也就是说随机的,那么MooTools是怎样保证按顺序解释的呢?先看下面这段代码:

var obj = {  
    Waa: "Waa",  
    aa: 'aa',  
    68: '68',  
    15: '15',  
    tt: 'tt',  
    '-7': '-7',  
    _: "___",  
    online: true  
};  
for(var k in obj){  
    console.log(k);  
}

 把它放在各个浏览器都执行一遍,你会发现IE、火狐、Safari浏览器的JavaScript解析引擎遵循的是较老的ECMA-262第三版规范,属性遍历顺序由属性构建的顺序决定,而Chrome、Opera中使用 for-in 语句遍历对象属性时会遵循一个规律,它们会先提取所有 key的 parseFloat 值为非负整数的属性, 然后根据数字顺序对属性排序首先遍历出来,然后按照对象定义的顺序遍历余下的所有属性。其它浏览器则完全按照对象定义的顺序遍历属性。

        这下明白了吧,只要你为类设计的方法、属性还有Mutator的名称不为数字就可以了(当然如果你非要有这样的嗜好,我也只能@#%$......)。请看下面的代码:

var Super = new Class({  
    log: function(){  
        console.log('Super');  
    }  
});  
var Mixin = new Class({  
    log: function(){  
        console.log('Mixin');  
    }  
});  
var Sub = new Class({  
    Extends: Super,  
    Implements: Mixin  
});  
var obj = new Sub();  
obj.log();//?

        在这里obj.log()会返回什么呢?对了是'Maxin',这里Sub类首先继承了Super类,Sub的原型实际就是Super类的一个实例,Super的log方法也就是成了Sub的原型上的一个方法,然后执行Implements Mutator 为Sub类的原型扩展了一个Mixin类的实例上的方法,这时Mixin类实例上的log方法就覆盖了Sub类原型上原来的log方法(继承自Super类)。

如果把Extends、Implements的顺序颠倒一下:

var Sub = new Class({  
    Implements: Mixin,  
    Extends: Super  
});  
var obj = new Sub();  
obj.log();  
//?

        这时obj.log()会返回什么呢?还是'Maxin'吗?其实这里返回的是'Super',Why?前面我们介绍了MooTools对Class构造函数解析时是按照我们设计的顺序解析的,所以在这里首先执行的是Implements Mutator,它首先为Sub类的原型扩展了一个Mixin类的实例上的log方法,然后才是对超类Super的继承,因为在JavaScrpt里每个对象只有一个原型,原型式继承的原理就是超类的一个实例赋予子类的原型,子类原来的原型这时会被超类的实例替换掉,所以这是Sub类原型的引用已经指向了超类的实例,而他自己的原型对象这时被消除了,所以之前从Mixin类得来的那个log方法,对不起跟着一起魂飞湮灭了,所以这里返回的是'Super'。
        当然如果你嫌不过瘾,那就在为Sub类添加一个log方法:

var Sub = new Class({  
    Implements: Mixin,  
    Extends: Super,  
    log: function(){  
        console.log('sub');  
    }  
});  
var obj = new Sub();  
obj.log(); //?

        你可以把Sub类的Implements、Extends、log来回颠倒一下看看效果,呵呵,再用implement方法在扩展一个试试:

var objMixin = {  
    log: function(){  
        console.log('objMixin');  
    }  
};  
var Sub = new Class({  
    Implements: Mixin,  
    Extends: Super,  
    log: function(){  
        console.log('sub');  
    }  
});  
Sub.implement(objMixin);  
var obj = new Sub();  
obj.log(); //?

        呵呵,别晕掉,一切都是为了把问题搞的跟明白不是......

        最后不要忘记两个重要的方法:parent()和protect(),这里就不多说了,在前面的Class源码分析里有详细介绍。

© 著作权归作者所有

共有 人打赏支持
DerekLi
粉丝 10
博文 5
码字总数 0
作品 0
济南
加载中

评论(3)

MagicSong
MagicSong
写的不错!
AnnieNie
AnnieNie
79
JavaScript继承详解(五)

文章截图 - 更好的排版 在本章中,我们将分析John Resig关于JavaScript继承的一个实现 - Simple JavaScript Inheritance。 John Resig作为jQuery的创始人而声名在外。是《Pro JavaScript Te...

solu ⋅ 2010/12/25 ⋅ 0

MooTools 1.2.2 发布

MooTools 1.2.2 主要是修正了一些bug,同时对 Class.js 文件进行了重写,原因是旧的 Class.js 的 this.parent() 运行得不够好,MooTools 1.2.2 的目的是为 MooTools 2.0 做好准备。新的 Clas...

红薯 ⋅ 2009/04/28 ⋅ 0

Dojo 之 面向对象

面向对象三大特性:封装、继承、多态。在熟悉了Java/C#/C++这些高级面向对象语言的语法结构后,我们或多或少会对javascript脚本语言的面向对象感到一些不适,function、prototype、call、app...

文艺小青年 ⋅ 2017/06/30 ⋅ 0

MooTools源代码导读

mootools模块 1.1. 模块结构 /Source 1.2. 模块功能 Core:MooTools框架中一些通用的函数,另外在这个模块内,会对原生的Javascript对象,比如Function等做一些拓展。常用的一些拓展框架对象...

knightuniverse ⋅ 2014/07/13 ⋅ 0

MooTools教程(2):DOM选择器

如果你还没有准备好,请先阅读上一篇《Mootools 1.2教程(1)——MooTools介绍》。我们讲了怎么引用MooTools 1.2以及怎么在domready里面调用你的脚本。 今天开始本系列教程的第2讲。在这一讲中...

halfcoder ⋅ 2010/12/12 ⋅ 0

mootools入门

介绍 MooTools是一个简洁,模块化,面向对象的开源JavaScript web应用框架。 它为web开发者提供了一个跨浏览器js解决方案。在处理js、css、html时候。 它提供了一个比普通js更面向对象的doc...

笔阁 ⋅ 2016/03/16 ⋅ 0

Prototype与MooTools创建简单类的比较

先来看Prototype的,官方地址是:http://prototypejs.org/learn/class-inheritance 范例如下: var Person = Class.create();Person.prototype = {initialize: function(name) { },say: func......

赵开锦 ⋅ 2011/08/17 ⋅ 0

MooTools 1.6.0 发布,重构 Gruntfile

MooTools 1.6.0 发布了,该版本主要是修复一些bug以及引入一些新特性。 主要更新: Core: Rename method in Array, Function, String and Number (#2758)(#2760) New feature: Class.Thenab...

阿紫 ⋅ 2016/09/11 ⋅ 5

mootool文档(core)

Mootools - Type:Core Core包含了Mootools的常用功能 Function: typeOf 返回对象的类型 语法: typeOf(obj) 参数: 1.obj-(对象)待检查的对象 返回值 'element' - (string) 如果对象是DOM元素节...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

大胆预测下几个JavaScript框架的走势

Posted on September 21st, 2008 in 前端开发 by lifesinger MooTools将在接下来的几年内像jQuery一样迅速窜红 而jQuery则会慢慢销声匿迹 YUI将不尴不尬的活着,YUI 3.x将成为小部分人的玩物...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

设计模式--装饰者模式

装饰者模式 定义 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。 通用类图 意图 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比...

gaob2001 ⋅ 55分钟前 ⋅ 0

JavaScript零基础入门——(八)JavaScript的数组

JavaScript零基础入门——(八)JavaScript的数组 欢迎大家回到我们的JavaScript零基础入门,上一节课我们讲了有关JavaScript正则表达式的相关知识点,便于大家更好的对字符串进行处理。这一...

JandenMa ⋅ 今天 ⋅ 0

sbt网络问题解决方案

转自:http://dblab.xmu.edu.cn/blog/maven-network-problem/ cd ~/.sbt/launchers/0.13.9unzip -q ./sbt-launch.jar 修改 vi sbt/sbt.boot.properties 增加一个oschina库地址: [reposit......

狐狸老侠 ⋅ 今天 ⋅ 0

大数据,必须掌握的10项顶级安全技术

我们看到越来越多的数据泄漏事故、勒索软件和其他类型的网络攻击,这使得安全成为一个热门话题。 去年,企业IT面临的威胁仍然处于非常高的水平,每天都会看到媒体报道大量数据泄漏事故和攻击...

p柯西 ⋅ 今天 ⋅ 0

Linux下安装配置Hadoop2.7.6

前提 安装jdk 下载 wget http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.7.6/hadoop-2.7.6.tar.gz 解压 配置 vim /etc/profile # 配置java环境变量 export JAVA_HOME=/opt/jdk1......

晨猫 ⋅ 今天 ⋅ 0

crontab工具介绍

crontab crontab 是一个用于设置周期性被执行的任务工具。 周期性执行的任务列表称为Cron Table crontab(选项)(参数) -e:编辑该用户的计时器设置; -l:列出该用户的计时器设置; -r:删除该...

Linux学习笔记 ⋅ 今天 ⋅ 0

深入Java多线程——Java内存模型深入(2)

5. final域的内存语义 5.1 final域的重排序规则 1.对于final域,编译器和处理器要遵守两个重排序规则: (1)在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用...

江左煤郎 ⋅ 今天 ⋅ 0

面试-正向代理和反向代理

面试-正向代理和反向代理 Nginx 是一个高性能的反向代理服务器,但同时也支持正向代理方式的配置。

秋日芒草 ⋅ 今天 ⋅ 0

Spring 依赖注入(DI)

1、Setter方法注入: 通过设置方法注入依赖。这种方法既简单又常用。 类中定义set()方法: public class HelloWorldOutput{ HelloWorld helloWorld; public void setHelloWorld...

霍淇滨 ⋅ 昨天 ⋅ 0

马氏距离与欧氏距离

马氏距离 马氏距离也可以定义为两个服从同一分布并且其协方差矩阵为Σ的随机变量之间的差异程度。 如果协方差矩阵为单位矩阵,那么马氏距离就简化为欧氏距离,如果协方差矩阵为对角阵,则其也...

漫步当下 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部