oo的一些概念

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小节讲解。

时间: 2024-08-09 02:20:19

oo的一些概念的相关文章

面向对象基本概念

面向对象基本概念 乔高峰  于深圳整理(2007-01-13) 面向对象(object-oriented ;简称: OO) 至今还没有统一的概念,我这里把它定义为:按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析.设计.实现软件的办法.通过面向对象的理念使计算机软件系统能与现实世界中的系统一一对应. 面向对象方法(Object-Oriented Method)是一种把面向对象的思想应用于软件开发过程中,指导开发活动的系统方法,简称OO (Object-Ori

C++中面向对象的理解

?? 1.对于OO(面向对象)的含义,并非每一个人的看法都是同样的. 即使在如今.假设问十个人,可能会得到15种不同的答案.差点儿全部的人都会允许继承和多态是OO中的概念.大多数人还会再加上封装. 另一些人会加上异常处理.而可能会没有人将模板也包括进去.问题的关键在于:对于某个特性是否是属于OO的,往往都存在着不同的观点.而每一种观点都有着热情的拥护者. 2.C++的标准化工作对C++最重要的贡献就是:对功能强大的抽象机制提供了更有力的支持,从而减少了软件的复杂性.C++并不只不过一种面向对象的

面向对象的由来和发展

OO方法起源于面向对象的编程语言(简称为OOPL).50年代后期,在用FORTRAN语言编写大型程序时,常出现变量名在程序不同部分发生冲突的问题.鉴于此,ALGOL语言的设计者在ALGOL60中采用了以"Begin……End"为标识的程序块,使块内变量名是局部的,以避免它们与程序中块外的同名变量相冲突.这是编程语言中首次提供封装(保护)的尝试.此后程序块结构广泛用于高级语言如Pascal .Ada.C之中. 60年代中后期,Simula语言在ALGOL基础上研制开发,它将ALGOL的块

数据库设计杂谈

注:本人开发经验尚浅,下文主要谈的是自己的一些想法,不足之处请指出. 最近半年时间都花在管理系统的开放上面,对数据库的设计有一些自己的想法,在我看来数据库设计的key point就是妥协.一个设计的比较好的数据库都是在业务逻辑.设计规约和便于开发这三者之前来回考量,从而获得3-win的结果.下面主要是在思考和总结的点. 如何设计出高灵活性的数据库 可以说在项目交付前,需求不断在变,如何在需求改变的同时尽可能减少对表结构的修改是我现在考虑的问题.对于一般情况而言,在设计的时候我们可以适当添加一些预

无法言喻的奥妙

学习指针断断续续两个星期,基本告一段落,心得笔记与大家一起分享知识,指针用我的体会来说,简直是玄之又玄,众眇之门.整个学习其实是围绕指针与指针变量两个关键点,指针与指针变量个人理解如下:指针:我们声明定义变量(×××.字符串.函数等),变量会存于常量区.栈内存等里面,指针就是用于指向他们存储的位置,更贴切的说指针也是需要开辟空间的,指针的值就是我们存储的变量.指针变量指针 变量只能存放指针,听起来很绕口,就是只能存地址,不可以存变量.两个符号操作如下*号用于取值操作,&用于取地址操作.光说基本是

极客学院Web前端开发技术实战视频教程 初级入门+高级实战++专家课程+面试指导

===============课程目录=============== ├<初级中级>│  ├<1. HTML5开发前准备>│  │  ├1.HTML5开发前准备.mp4│  │  └2.开发前的准备-快捷键.mp4│  ├<10. React.js>│  │  ├React.js简介.txt│  │  ├<1.React 概述>│  │  │  ├React 开发环境搭建.mp4│  │  │  ├编写第一个 React 程序.mp4│  │  │  └什么

[Lua学习]简单的类定义(OO概念)

1 -- 二维向量类 2 3 local P = { 4 x = 0, 5 y = 0 6 } 7 8 Vec2 = P 9 10 --setfenv(1, P) 11 12 local function optAdd(a, b) 13 local o = P:new() 14 o.x = a.x + b.x 15 o.y = a.y + b.y 16 return o 17 end 18 19 function P:new(x, y) 20 o = {} 21 22 -- 构造 -- 23 o

Java oo 概念总结

1.  Java语言的特点是什么? 简单  面向对象   跨平台    多线程   健壮性安全性   垃圾回收机制 2.如何编译和执行java文件?产生帮助文档用什么命令? 编译:   javac    文件名 执行:   java     类名 产生帮助文档   javadoc  文件名 3.虚拟机的工作流程是什么? 编写源文件(*.java)------编译成*.class字节码文件------类加载--------字节码校验----解释器----操作系统. 4.main方法怎么书写? Pu

从源码看 Promise 概念与实现

Promise 是 JS 异步编程中的重要概念,它较好地解决了异步任务中回调嵌套的问题.在没有引入新的语言机制的前提下,这是如何实现的呢?上手 Promise 时常见若干晦涩的 API 与概念,它们又为什么存在呢?源码里隐藏着这些问题的答案. 下文会在介绍 Promise 概念的基础上,以一步步代码实现 Promise 的方式,解析 Promise 的实现机制.相应代码参考来自 PromiseJS 博客 及 You don't know JS 的若干章节. Why Promise (有使用 Pr