js设计模式基础——继承

作者:bibodeng 发布于:2013-12-4 23:59 Wednesday 分类:web开发

js设计模式基础——继承

by bibodeng 2013-12-04

js中的继承

js中的继承分为几种:

  • 类式继承 (构造函数的prototype链扩展) extend
  • 原型式继承 (从对象的角度) clone
  • 掺元类 (混合多个类)

类式继承

使用原型链的方式,让构造函数的原型指向另外一个对象(注意是对象)。我们平常做的比较多的,就是创建一个新类,然用用prototype扩展这个类,然后生成的类的对象实例则具备了原型链对象中的方法和属性了。

让一个类继承另外一个类的四部曲:

  • 设置原型对象
  • 恢复构造函数
  • 执行构造函数(构造函数也执行父类构造函数)
  • 生成新对象

然而在new的过程中,将会调用自身的构造函数,让一个类继承另外一个类,就需要它调用一次父类的构造函数,从而在this中声明各种属性。并且把构造函数设置回自己的构造函数(因为会覆盖掉)。现在为了实现两个类之间的继承,实现一个模拟继承:

function extend(subClass, superClass){
    var F = function() {};
    F.prototype = superClass.prototype; // 这句挺巧妙
    subClass.prototype = new F();   // 相当于调用过了superClass的构造函数,并且将F的对象实例赋给了subClass的prototype对象
    subClass.prototype.constructor = subClass; // 恢复构造函数
}

原型式继承

从原有对象的基础上进行修改变换。类的基础是一个对象:

var Person = {
    name: 'ren',
    talk: function(){
        console.log("hi, my name is "+this.name);
    }
}

// 克隆方法,将obj放到新对象的原型链中
function clone(obj){
    function F(){};
    F.prototype = obj;
    return new F;
}

// 原型继承
newObj = clone(Person);

在clone之后,对于从原型继承而来的属性,直接更改的话会改变原型对象中的数据,会对别的子类产生影响,而如果给一个属性赋值的方式,如obj.name = "bibo" 将会新建一个新对象自己的属性。所以,要改变某个属性之前,先为它创建新的副本,而不是让它默认使用原型的值,这也能够解决上面所谓的读写不对称 ,这多少和我们之前的继承认识有所不同。不过可以使用hasOwnProperty来区分是实际成员还是继承的成员,因为hasOwnProperty是不把原型链中的属性或方法算在内的。

多类继承(混合两个类)

使用的是将一个类中的属性拷贝到另外一个类中。这样就把两个类(一个函数)的属性给混在一起了。

function mix(receivingClass, givingClass){
    if(arguments[2])
    {
        // 可能不止一个类掺入,存起所有prototype
        for(var i=0, len = arguments.length; i < len; i++){
            receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]];
        }
    }
    else
    {
        for(methodName in givingClass.prototype){
            if(!receivingClass.prototype[methodName]){
                receivingClass.prototype[methodName] = givingClass.prototype[methodName];
            }
        }
    }
}

上面的函数用于掺杂多个类的prototype属性。一般是继承prototype对象里面的东西:

var ClassA = function(){};
ClassA.prototype = {
    // 这里的才是prototype对象中的属性和方法
    method1: function(){console.log("method 1 call")}
}

// 假设有另外一个类:

var ClassB = function(){};

mix(ClassB, ClassA); // 将method1给混到ClassB中去

大部分代码都是从书中摘抄的,这里只是稍微梳理一下各种代码。其实最根本的还是弄清原型链的关系。对于问题的敏锐性,是能够注意到事物之间的关联,理清关键联系,这样能够朝着目标解决问题。


end

阅读全文>>

标签: web js 继承

评论(0) 引用(2) 浏览(1739)

简析js设计模式接口基础

作者:bibodeng 发布于:2013-12-2 19:56 Monday 分类:web开发

简析js设计模式接口基础

by bibodeng 2013-12-02

想起要对js设计模式中一些基础的代码做一个简单分析,让自己印象更加深刻。例如接口,继承,闭包等等,方便以后要的时候直接拿来。

接口

接口,学过Java的同学肯定知道,声明一个接口,里面有若干方法,而一个类负责实现(implements)它,语言本身的机制会强制该类必须实现接口中声明的所有方法,否则就会报错。实现接口的目的是为了提供一组通用的叫法,让不同的对象实现它。很常见的就是在组合模式中,父元素和子元素都实现了相同的接口,从而可以很直接地将请求从任意一层传递下去。总之,接口能够提供一个通用的方法库,也要保证各类都有实现所有方法。接口在js中的实现方法有三种:

  • 注释法 (就是用注释来说明)
  • 属性检查法
  • duck type(会呱呱叫的都是鸭子)

属性检查法

注释法就不详细看了,因为它就是用注释声明一些接口,而不做任何检查,完全靠人工检查是否实现了相应的方法。而属性检查法,相对来讲严格一点,它将一组接口的名字都放入一个数组中。

// 这是后面组合模式表单的一个例子
var ClassA = function(){
    // 声称自己有一组接口
    this.interfaces = ['Composite', 'FormItem'];
}

为了检查是否实现了相应的接口,就检查该类的实例是否具有某个接口,这个某个接口是作为字符串传入需要检查的接口名。

// 模仿implements
function implements(obj){
    // 对传入的参数(接口名进行检查)
    for (var i=1; i < arguments.length; i++)
    {
        var interfaceName = arguments[i];
        var interfaceFound = false;
        // 检查声称的接口 比对两个数组需要两个循环
        for (var j=0; j<obj.interfaces.length; j++){
            if (obj.interfaces[j] == interfaceName){
                interfaceFound = true;  // 接口j找到了
                break;
            }
        }
        // 只要有一个接口没有实现
        if(!interfaceFound){
            throw {
                name: 'interface error',
                msg: 'some interfaces not found in obj'
            }
            return false;
        }
    }
    return true;    // 全部通过检查
}

// 调用方法
if (!implements(obj, 'Composite', 'FormItem')){
    ...
}

这次只是把这些接口名都放到一个数组中,但是还是没有确保在ClassA中实现接口中的方法(还是以注释的方式说明)。在实践中看起来也没啥用处。我们需要的是真正能够检查对象的方法,我们瞬间想到了for (var index in obj) 对每个方法进行检查。而我们的接口,也应该放在一个像这样的对象中,它能够维护接口的名字和各种方法名。

{
    interfaceName: 'Composite',
    methods: ['add', 'remove', 'getChild']
}

初步的思想是有了,但是实现要灵活,能够生成一个如上的对象。duck typing就是这样做的:

鸭式辨形

会呱呱叫的两只脚走路的会游泳的就是鸭子。我们生活中常常是一个经验主义者,通过这样的方法来判断事物。所有,理解起来也不是很难:

// 接口对象
var Composite = new Interface('Composite', ['add', 'remove', 'getChild']);

// 要得到上面的对象,我们写一个构造函数专门用来新建接口对象
function Interface(interfaceName, methods){
    this.interfaceName = interfaceName;
    this.methods = methods;
    // new操作将返回this
}

// 如果要严密一点,就需要检查参数的个数和类型

这次就不用注释了,而且代码很明了。声明了一个接口对象Composite,它的名字叫做Composite,具有addremovegetChild三个方法。那么如何声明实现了该接口,并且用什么来确保对象实现了我们接口声明的方法呢?

这次都不用声明实现了该接口,只要实现了相应的方法就是实现了该接口。所以不用显式地声明implements了什么。而是在某个方法之前用ensureImplements来检查。至于设计成Interface的内置方法,还是普通函数,都是可以的。

// obj, interf1, interf2
Interface.ensureImplements = function(obj){
    if (arguments.length < 2){
        throw new Error("arguments require for at least 2");
    }

    // 依次检查 这次的参数是interface实例,不再是字符串
    // 而一个字符串数组也变成了真正的对象的属性
    for (var i=1; i<arguments.length; i++){
        var interface = arguments[i];
        // 严格的类型检查
        if (interface.constructor !== Interface){
            throw new Error("argument " + i + " is not the instance of Interface Class");
        }

        for (var j=0; j<interface.methods.length; j++){
            var method = interface.methods[j];
            if (!obj[method] || typeof obj[method] !== 'function'){
                throw new Error("ensureImplements error: method" + interface.methods[j] +
                    ' in interface '+ interface.interfaceName + ' was not found.');
            }
        }
    }
}

// 调用示例
function foo(formObj){
    // 不满足条件回报错
    Interface.ensureImplements(formObj, Composite, FormItem);

    // 使用接口中的方法
    formObj.remove();
    ...
}

主要就是实现一个Interface类,供生成实例,也提供一个ensureImplement方法。只要引入了这个类,就可以使用new一个Interface,然后检查的方式严格要求类实现了接口中的方法。但是我总觉得少了一步,就是声明一下某个类实现了某个接口。当然也可以用数组将所实现的接口都存一个对应的应用,如{'Composite': Composite}。但是这样看起来就不像是鸭式辨型了。


end

阅读全文>>

标签: web js 接口 interface

评论(0) 引用(2) 浏览(1845)

[书]读《js设计模式》

作者:bibodeng 发布于:2013-11-29 11:17 Friday 分类:web开发

读《js设计模式》

by bibodeng 2013-11-29

迫切的需求

接触前端大概一年了,由于许多深入的东西都不懂,所以做不出高级的东西。对于稍微复杂一点的需求,都觉得难以下手。于是意识到了要学学设计模式了,所以就翻开(准确来说是点开了)这本《javascript设计模式》。由于有了js的基础,在读了《js编程精粹》之后,对于这门语言有了喜爱和习惯,于是这...

阅读全文>>

标签: web js 继承 笔记 设计模式

评论(0) 引用(1) 浏览(1668)

事件代理实现

作者:bibodeng 发布于:2013-11-3 11:26 Sunday 分类:web开发

事件代理实现

by bibodeng 2013-10-29

事件代理的原理

所谓事件代理,就是说让另外一个元素,一般是父元素来绑定事件,然后处理的是子元素被点击后的逻辑。这样的目的是减少绑定事件的消耗,因为往往一个父元素下有很多个相同的子元素,它们所绑定的事件也是一样的,故而可以将这个消耗给转移到同一个绑定中,既提升效率,也使得程序变得优雅。我在博客园找到一篇事件代理的[...

阅读全文>>

标签: javascript web 事件

评论(0) 引用(2) 浏览(1494)

CSS3 3D六面体效果

作者:bibodeng 发布于:2013-10-23 17:55 Wednesday 分类:web开发

CSS 3D效果

by bibodeng 2013-10-23

碎碎念

无意之中看到beiyuu写的CSS3动画详解,而我之前没有怎么系统学习过CSS3和HTML5,故而对其炫酷的效果非常动心,并且觉得这个技术在一些地方肯定非常棒。他的讲解例子很丰富,但是我还是花了一些功夫去理解。轻松获得的东西,也容易轻松失去,如果其中...

阅读全文>>

标签: web css3 动画

评论(0) 引用(0) 浏览(2512)

web优化笔记

作者:bibodeng 发布于:2013-5-20 14:17 Monday 分类:web开发

方向

有一段时间因为找不到实习而有点郁闷,必须承认今年的就业形势比较严峻,上次去UC笔试,居然连面试机会都不给!恰好看到了@Fenng 写的这篇 现在的计算机专业学生怎么这个样? 感觉戳中了很多人的要害。回头看看自己真的是太急躁了,总想找个好的工作,而不考虑自己到底有怎样的深度。仔细想想,还是要沉着冷静,好好将自己的技术提升上来。看了...

阅读全文>>

标签: 分享 web js

评论(0) 引用(122) 浏览(12121)

js的面向对象与继承

作者:bibodeng 发布于:2013-5-12 21:20 Sunday 分类:web开发

基础

js包含三部分:1,ECMAScript语法 2,DOM 3,BOM. 应该说ECMAScript这种东西,语法和许多概念都是源于那些高级语言(C/C++, Java),单就面向对象和继承来说,js又属于比较特殊的,它的类是一个构造函数,函数又属于一种对象,而它又不支持直接的继承,故而就需要使用prototype或者是冒充对象来实现继承和多...

阅读全文>>

标签: javascript web 前端 深入 对象 继承

评论(0) 引用(0) 浏览(1660)

带微信功能的sae博客

作者:bibodeng 发布于:2013-5-9 17:21 Thursday 分类:web开发

准备

在安装之前,需要准备好博客系统的源代码(含微信响应功能,使用python为sae定制),这可以从github上下载:

pyweixin_saelog: 

会用git的同学可以直接cd到想要放置的命令,如/home/bibodeng/git/下,然后在终端运行如下命令:

git clone https://github.com/bibodeng/pyWeiXin_SAElog.git

&nb...

阅读全文>>

标签: web python weixin blog github

评论(0) 引用(15) 浏览(4451)

专注前端开发

作者:bibodeng 发布于:2013-4-24 20:32 Wednesday 分类:web开发

2013-04-23 8:56:24

写在前面

上次“第一次面试”的时候,我的面试官告诉我:“你东西是有了,但是不够专”,其实之前我还在犹豫是走前端还是服务器道路,现在狠下心来,专注于前端开发,埋头理解前端原理,性能优化,高质量代码编写等。故而我找来了几本书——web前端修炼之道/HTML5/性能优化最佳实践。还好,我懂得怎么去找比较好的博客和书籍来看,去成为一个卓越的前端工程师。我想...

阅读全文>>

标签: web python 前端 深入

评论(0) 引用(9) 浏览(1681)

微信公众开发——使用消息接口

作者:bibodeng 发布于:2013-4-19 9:49 Friday 分类:web开发

南苑随笔app

之前写了一篇搭建sae的python平台,通过微信公众平台验证的博文。现在就是要承上启下,开始开发的第一步。也许你会说开发的第一步就是写代码。那我会对你表示鄙视,尽管南苑随笔是个很简单的应用,但是多少也还需要设计一下。确定一下需求,为了将来能够吸引到粉丝来关注我的公众号,我必须要定位好我的app,然后提供优秀的内容,并确定它的运营模式,才能进一步地提升我们的应用水准。

需求分析

首先,...

阅读全文>>

标签: web weixin django poster

评论(2) 引用(3) 浏览(5196)

Powered by emlog 京ICP备16017775