http://docs.kissyui.com/5.0/guides/base/oo.html

JavaScript 语言自成体系,自有一套代码重用的模式,这些常见的代码重用模式可以在《Javascript 设计模式》、《JavaScript 编程模式》中找到理论基础。KISSY 即是实践了这些典型的代码重用模式,并作为 KISSY 代码库的面向对象的核心,向高层代码提供语言的完备性支撑。

这些理论基础大都来自"javascript 编程模式"一书:

KISSY 中面向对象的范畴包含两个方面,本篇讲解第一方面

  • 语言层面:JS 语言特有的编程模式

    • 面向对象相关的模式
    • JS 语言增强的工具函数
  • 最佳实践:KISSY 对于面向UI、模块生命周期的封装,包括组件模式、插件模式等

概要

JavaScript 语言没有原生类的概念,对象之间共享方法的关键渠道是通过原型。而具备某一类原型方法的'模板对象',通常被称作基类,子类除了调用基类的构造器(手动调用)外,最重要的就是要拥有基类的行为能力(继承基类原型上的方法)。这个过程中涉及到五种典型的行为:

  • 混合 mix
  • 克隆 clone
  • 扩充 augment
  • 继承 extend
  • 合并 merge

以 kissy 的 API 为例,merge 和 augment 都是基于 mix 方法,本质上利用了 JS 的动态特性,在运行时为对象增减成员;

extend 方法的实现比较典型,总体思路是子构造器的原型对象指向父构造器的一个实例,具体有一些细节问题要处理。类继承体系中继承的是对象的模板(即类),JS 没有对于对象的更高一层的抽象数据结构,即使有 constructor 这种东西,它本身也只是 function 对象而已。

mix

mix (receiver , supplier [ , overwrite = true , whitelist , deep ]) => Object

将 supplier 对象的成员复制到 receiver 对象上。参数:

  • receiver (object) – 属性接受者对象.
  • supplier (object) – 属性来源对象.
  • overwrite (boolean) – 是否覆盖接受者同名属性.
  • whitelist (Array) – 属性来源对象的属性白名单, 仅在名单中的属性进行复制.
  • deep (boolean) – 是否进行深度 mix (deep copy)

mix 默认不是递归进行的. 如果其中一个属性为对象或者数组,那么他将会被接下来对象的同名属性对应的值所代替,即值不会被合并。 如果设置了参数 deep = true ,那么会对数组和简单对象KISSY.isPlainObject()递归合并.

supplier undefined 的属性值不会被复制,不过对象从原型继承下来下的值则会被复制.

该方法仅适用于 javascript 对象,不要在浏览器对象上调用,例如 node.style

简单 mix

require(['util'], function(Util){
var r = { a: 'a', b: 'b' };
Util.mix(r, { c: 'c' });
console.log(r.c); // => 'c' Util.mix(r, { a: 'a2' }, false);
console.log(r.a); // => 'a' Util.mix(r, { e: 'e', f: 'f' }, true, ['f']);
console.log(r.e); // => undefined
console.log(r.f); // => 'f'
})

深度mix

var object1 = {
apple: 0,
banana: {weight: 52, price: 100},
cherry: 97
};
var object2 = {
banana: {price: 200},
durian: 100
}; /* merge object2 into object1, recursively */
Util.mix(object1,object2,undefined,undefined,true); console.log(object1); // => { apple: 0, banana: { weight: 52, price: 200 }, cherry: 97, durian: 100 }

mix是最自然也是最简单的为 JS 对象添加特性的方式,具体实现就是将一个对象的(所有或指定)属性指向给另一个对象,在静态语言中是无能为力的。

虽然 Yahoo 将这种方式学院式地命名为“augmentObject”并且声称使用它的合适场合是在“扩充一个‘静态类’”时。所谓“静态类”这种说法,只能说是中静态类语言的遗毒太深,什么概念都要一一映射至其上。事实上,“静态类”对应 JS 中的概念是“非构造器对象”,比如字面量对象。而之所以 Yahoo 强调“静态类”,那是因为“静态类”和构造器之间间有一个显区别,前者没有 prototype 属性。

补充一点,“静态类”也可以是构造器,只不过它的 prototype 没有多大意义(比如指向 {})。

事实上,这个方法是 augment 和 merge 的基础。可以看到,JS 中直接对对象进行各种操作其实非常方便,类什么的都是浮云。

merge

merge (s1,s2[,...]) => Object

将多个对象的成员合并到一个新对象上. 参数中, 后面的对象成员会覆盖前面的。如果用mix混合对象时,receiver 会被改变,如果想要保留原始的 receiver ,可以使用 KISSY.merge()

var object=Util.merge(object1,object2);

简单例子:

var a = { a: 'a' },
b = { b: 'b' },
c = { b: 'b2', c: 'c' }; var o = Util.merge(a, b, c);
console.log(o.a); // => 'a'
console.log(o.b); // => 'b2'
console.log(o.c); // => 'c'

简单情况下 merge 方法常用来合并配置信息. 推荐使用 Base 处理属性配置.

extend

extend (r,s[,px,sx]) => Function

让函数对象 r 继承函数对象 s,参数

  • r (function) – receiver,将要继承的子类函数
  • s (function|object) – supplier,继承自的父类函数
  • px (object) – prototype members, 需要添加/覆盖的原型成员
  • sx (object) – static members, 需要添加/覆盖的静态成员.

    function Bird(name) { this.name = name; } Bird.prototype.fly = function() { alert(this.name + ' is flying now!'); };

    function Chicken(name) {

      Chicken.superclass.constructor.call(this, name);

    } Util.extend(Chicken, Bird,{

      fly:function(){
    Chicken.superclass.fly.call(this)
    alert("it's my turn");
    }

    });

    new Chicken('kissy').fly();

extend 方法是 KISSY 里类继承的实现方式. 书写 JavaScript 代码时, 请忘记传统 OO 里的继承体系。子类方法中可通过 superclass 来访问父类函数的原型, 进而调用父类方法.

Util.extend 像 Node.js 里的 util.inherits,就是用于声明两个类的继承关系,与 util.inherits 相比,它更为贴心,还会维护 superclass 和 superclass.constructor。

注意构造函数体内,通过 Chicken 类上的 superclass 属性,子类不再需要显式写明父类的名称, 只需要直接调SubClass.superclass.constructor.call(this, attrs) 即可。

而在方法内,也可以通过 SubClass.superclass 拿到父类上的方法,类似其他编程语言中的 super 之类。

augment

augment(r, s1 [, s2 , ...], ov = true, wl) => Function

将 s1,s2.... 的 prototype 属性的成员复制到 r.prototype 上。这时被复制的成员来自于一个Fucntion对象,这个对象一般被称为掺元类(mixin class)。比如 KISSY 里的 CustemEvent 就是一个掺元类。掺元类只是被扩充用的。参数说明:

  • r (function) – 将要扩充的函数
  • ...s1 (function|object) – 扩充来源函数或对象. 非函数对象时复制的就是 s 的成员.
  • ov (boolean) – 是否覆盖 r.prototype 同名属性.
  • whitelist (Array) – 属性来源对象的属性白名单, 仅在名单中的属性进行复制.
var Shoutable = {
shout: function() { alert('I am ' + this.name + '.'); }
}; function Dog(name) { this.name = 'Dog ' + name; }
function Pig(name) { this.name = 'Pig ' + name; } Util.augment(Dog, Utilhoutable);
Util.augment(Pig, Shoutable); new Dog('Jack').shout(); // => I am Dog Jack.
new Pig('Mary').shout(); // => I am Pig Mary.

augment 方法在 KISSY 里非常基础非常重要. 传统 OO 语言里, 可以通过继承或接口来实现共性方法. 在 JavaScript 里, 通过 mixin 特性, 一切变得更简单. augment 是动态语言 mixin 特性的体现, 灵活运用, 能让代码非常优雅简洁.

clone

对象的值的拷贝,绕过引用的拷贝。


有了 Util.augment,我们可以很方便得扩展类的原型;有了 Util.extend,我们可以很方便地继承;那么 KISSY 对属性 getter、setter 有什么好的解决方案么?答案自然是 Base。

顾名思义,Base 是个基础类;而这个类,也是通过 Util.augment 等搞定的。在Base小节讲解。

oo的一些概念的更多相关文章

  1. OO 面向对象的概念

    面向对象的概念 一.什么是面向对象? 传统的:世间万物都是对象.例如:桌子,凳子,电脑等: 个人理解: 1.软件开发方法: 2.面向对象是一种解决问题和分析问题的(编程)一种思想: 3.他是通过面向过 ...

  2. OO Unit 1 表达式求导

    OO Unit 1 表达式求导 面向对象学习小结 前言 本博主要内容目录: 基于度量来分析⾃己的程序结构 缺点反思 重构想法 关于BUG 自己程序出现过的BUG 分析⾃己发现别人程序bug所采⽤的策略 ...

  3. CSS:CSS 在工程中改变——面向对象的CSS (OO CSS)

    一.OO  CSS 的概念解读 (一)众多开发者忽视了CSS的表现,认为其太过简单,是一种机械的工作,而把更多关注在JS的性能或者其他方面. (二)OO CSS 将页面可重用元素抽象成一个类,用cla ...

  4. Abstract Factory Step by Step --- 抽象工厂

    抽象工厂是创建型模式的代表,其他的还有单件(Singleton).生成器(Builder).工厂方法(Factory Method)以及原型(Prototype),模式本身没有好坏之分,只有适用不适用 ...

  5. UML学习备忘

    两大类UML图: 行为图(behavior diagrams)和结构图(structure diagrams)     行为图将引导系统分析员分析且理清"系统该做些什么"?系统分析 ...

  6. 《大象Think in UML》阅读笔记之一

    Think in UML这一书以UML为载体,将面向对象的分析设计思想巧妙地融合在建模UML当中,通过一些实例将软件系统的开发过程中的一些知识有机地结合起来.全书共分为四篇:准备篇.基础篇.进阶篇和总 ...

  7. [JavaScript]Prototype继承

    JavaScript相对于其他的编程语言是比较简单的,只要吃透了Prototype和Closure(闭包),基本上就可以说精通JavaScript了. JavaScript里如何实现向Java语言的O ...

  8. C++中面向对象的理解

     1.对于OO(面向对象)的含义,并非每一个人的看法都是同样的. 即使在如今.假设问十个人,可能会得到15种不同的答案.差点儿全部的人都会允许继承和多态是OO中的概念.大多数人还会再加上封装. 另 ...

  9. 【转载】Abstract Factory Step by Step --- 抽象工厂

    抽象工厂是创建型模式的代表,其他的还有单件(Singleton).生成器(Builder).工厂方法(Factory Method)以及原型(Prototype),模式本身没有好坏之分,只有适用不适用 ...

随机推荐

  1. Backbone学习记录(6)

    路由 backbone将路由规则和一个方法名绑定到一起,来控制单页的hash,以及单页的前进后退. var UserRouter = Backbone.Router.extend({ routes: ...

  2. B. Code For 1 一个类似于线段树的东西

    http://codeforces.com/contest/768/problem/B 我的做法是,观察到,只有是x % 2的情况下,才有可能出现0 其他的,都是1来的,所以开始的ans应该是R - ...

  3. poj3252Round Numbers

    链接 也算是组合 以前按组合做过一次 忘记怎么做的了 这次按dp写的 dp[i][j][g][k] 表示第i位为k(0|1)而且有j个1,g个0的情况数 貌似写的麻烦了...这一类的题,进行逐位计算就 ...

  4. AJPFX总结private关键字

    private关键字        什么是private关键字?                它是一个修饰符,代表私有的意思,它可以修饰成员变量和成员方法 private关键字的特点?        ...

  5. logback日志异步打印

    最近碰到一个问题:客户的服务器程序偶尔出现请求响应过慢的情况,通过查看日志发现RSA验证签名的代码执行超过20秒,而正常情况下只需要16毫秒. RSA证书是服务器启动就加载好的,不存在读文件慢的问题. ...

  6. poj3616 Milking Time

    思路: dp. 实现: #include <iostream> #include <cstdio> #include <algorithm> using names ...

  7. hihocoder offer收割编程练习赛9 B 水陆距离

    思路: 宽搜,多个起点. 实现: #include <iostream> #include <cstdio> #include <algorithm> #inclu ...

  8. Android 使用GridView+仿微信图片上传功能(附源代码)

    由于工作要求最近在使用GridView完成图片的批量上传功能,我的例子当中包含仿微信图片上传.拍照.本地选择.相片裁剪等功能,如果有需要的朋友可以看一下,希望我的实际经验能对您有所帮助. 直接上图,下 ...

  9. Hibernate中的inverse和cascade属性

    Hibernate中的inverse和cascade属性 inverse的值有两种,"true"和"false".inverse="false&quo ...

  10. SPICE-HTML5 鼠标指针BUG修复

    研究SPICE,找到了他们官方指定的HTML5客户端.下载下来用一下,发现跟网页VNC的水平差不多了.http://www.spice-space.org/page/Html5 服务端直接用QEMU起 ...