信息服务社交网站设计与实现

作者:bibodeng 发布于:2014-5-12 21:50 Monday 分类:web开发

信息服务社交网站设计与实现

by bibodeng 2014-05-12

缘起

一直以来想要尝试实现一个社交网站,好让自己体会一把马克的瘾。于是在毕业论文选题的时候,选了《信息服务社交网站设计与实现》这个题目,指导老师是曾碧卿老师,事实证明他非常地靠谱。一开始我只是打算实现一个师兄认识师妹那种社交网站,但是老师给我的意见是结合地理信息服务,以及电子商务,我顿时就傻眼了,...

阅读全文>>

标签: python django 毕业设计 论文 社交 sae

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

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) 浏览(1781)

简析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) 浏览(1888)

[书]读《js设计模式》

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

读《js设计模式》

by bibodeng 2013-11-29

迫切的需求

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

阅读全文>>

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

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

重写share2SNS

作者:bibodeng 发布于:2013-11-21 10:48 Thursday 分类:web开发

重写share2SNS

by bibodeng 2013-11-20

前言

前段时间,@myunlessor 兄跟我讨论的时候提到我之前用的那个分享到SNS网站的js写得并不够优雅,有许多冗余的地方。而我最近也在看javascript的设计模式,发现代理模式非常适合这种用来发送一组GET请求的情况,尤其是参数较少的时候。于是我就试着实现一个代理模式实现的版本。 ...

阅读全文>>

标签: javascript 重构 设计模式

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

事件代理实现

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

事件代理实现

by bibodeng 2013-10-29

事件代理的原理

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

阅读全文>>

标签: javascript web 事件

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

用js实现快排加演示-js排程初探

作者:bibodeng 发布于:2013-10-25 8:27 Friday 分类:web开发

用js实现快排加演示

by bibodeng 2013-10-24

缘起

有很多时候,我们都是需要重新做一个轮子,才知道轮子究竟是什么样子的,然后就可以在下一次碰到这种情况时能够立马写出来,并且能写得很好。本来我打算写一个快排,然后在页面中进行演示,我知道已经有很牛的人实现过了,但是我做这个的时候,遇到了一些困难,使我想起了前段时间想要写某个锁机制队列的时候,后来发现...< q) // 需要排序的元素个数不为0 { x = partition(arr, p, q); // 对数组进行partion处理 qsort(arr, p, x-1); // x之前部分 x是该轮确定位置的元素 qsort(arr, x+1, q); // 2次递归 } };

var partition = function(arr, p, q)
{

    var tmp = 0,
        i   = p,
        j   = q + 1,
        base = arr[p];  // 首元素作为基准

    // 将数组分成两部分,大于base的,小于base的

    while (1)
    {

        while (arr[++i] <= base && i < q);

        while (arr[--j] >< total; i++)
    {
        myArr.push(parseInt((Math.random() * 450)));    // 0 - 450
    }

    // 绘制方格
    qsort(myArr, 0, myArr.length-1); 
});

为了能够体现出排序的可视化效果,我打算绘制一些小方格排列在一起,就像下面这样:

排序可视化

实现的代码并不麻烦,在ready中加入绘制方格的代码:

// 绘制方格
var str = '';
for (var j = 0; j < total; j++)
{
    str += "<li class='normal' style='height:"+myArr[j]+"px;'></li>< q) // 需要排序的元素个数不为0
    {
        x = partition(arr, p, q);   // 对数组进行partion处理

        setTimeout(function(){
            qsort(arr, p, x-1);     // x之前部分  x是该轮确定位置的元素
        }, 1000);

        setTimeout(function(){
            qsort(arr, x+1, q);     // 2次递归
        }, 2000);

    }

    console.log('after sort', arr);
};

并且setTimeout这东西,在循环下,是很耗费内存的,会导致页面奔溃,并且它之内将逻辑包围在一个函数参数里面,不太好。当把for循环换成setInterval调用时,元素操作效果倒是流畅了,但是排序结果却不正确了。原因是后续代码已经开始运行了。

异步的麻烦与解决办法

异步的麻烦,是真麻烦。我思考了一下,将排序算法和DOM操作混在一起是很野蛮的做法,没有做到数据加工和体现的分离。而当前状态又需要重绘,才能体现出其动态效果,但是重绘的代价也太大了,左思右想,没有想到好的解决办法,于是找到陈皓提到的日本程序员写的排序可视化,太强大了,效果也是一级棒,不过要细细剖析源码才知道它是如何实现的,这个改天再一探究竟,今天我要隆重介绍一下一个相当优雅的排程小程序,个人觉得写得相当优雅。

我们做很多编程工作时,往往想要同步(这里的同步指的是确定顺序,而不是不确定),例如在进行ajax请求时,回调结果往往要等一段时间才能返回,但是我们的程序的return却不知道要从哪里返回,如果在回调的外面,则等不到结果就返回了,如果在回调函数里面,则又返回不到正确的地方,这个时候就很有必要同步了。而一个排程的程序,对各个操作进行同步互斥,则可以让它们乖乖一个接一个按顺序执行,这就好比操作系统里面对资源的锁。具体可以参看myunlessor写的排程策略详解。直接上代码吧:

// 排程策略 - 全局定义
var schedule = (function (self) {
  var paused = false, // 标记状态
      queue  = [];     // 队列

  // 入队
  self.join = function (fn, params) {
    params = params || {};
    var args = [].concat(params.args);

    queue.push(function (_) {
      _.pause();
      setTimeout(function () {
        fn.apply(params.context || null, args);
        _.resume();
      }, params.delay || 1);
    });

    return exec();
  };

  self.pause = function () {
    paused = true;  // 忙碌
    return this;
  };

  // ready and call next
  self.resume = function () {
    paused = false; // 空闲
    setTimeout(exec, 1);
    return this;
  };

  function exec() {
    if (!paused && queue.length) {
      queue.shift()(self);  // 出队
      if (!paused) self.resume();
    }
    return self;
  }

  return self;
}(schedule || {})); // 立即执行,self就是schedule本身

我对着这个程序看了十来分钟,越看越有味道,从这个程序中可以看到javascript的很多good part,暂时没有看到缺陷,例如[],用成了活生生的队列,使用push和shift进行入队出队操作。还有闭包,直接返回一个self,本身参数传的是schedule,而schedule本身是刚刚定义的,需要赋值的,这一切看起来多么地神奇,还有返回this,强大的链式调用,有木有,额有点跑题了。下面我们就应用到我们的排序中:

var qsort =  function(arr, p, q)
{
    var x;
    if (p < q)  // 需要排序的元素个数不为0
    {
        x = partition(arr, p, q);   // 对数组进行partion处理

        schedule
        .join(qsort,{
            delay: 100,
            args: [arr, p, x-1]
        })
        .join(qsort, {
            delay: 100,
            args: [arr, x+1, q]
        });
    }
};

一切都相当优雅。当我打开浏览器测试时,发现,有了排程,而不是死板的setTimeout,动画变得流畅了很多。接下来的目标是接着优化partition里面的代码,使得这个过程也看起来很流畅。

var partition = function(arr, p, q)
{

    var tmp = 0,
        i   = p,
        j   = q + 1,
        base = arr[p];  // 首元素作为基准

    $list.attr('class', 'normal');
    schedule
    .join(showBase, {
        delay: 0,
        args: [p]
    });

    while (1)
    {

        while (arr[++i] <= base && i < q)
        {
            ;// 只要是小于base且没到结尾就一直前进
            schedule.
            join(moveSelectedRight,{
                delay: 50,
                args : [i]
            });
        }

        while (arr[--j] ><p class="readmore"><a href="http://www.bibodeng.com/?post=135">阅读全文&gt;&gt;</a></p>

标签: 算法 排序 js 异步 同步

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

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) 浏览(2576)

理解JSONP原理与使用

作者:bibodeng 发布于:2013-10-10 23:51 Thursday 分类:web开发

关于JSONP

写在前面

之前也不知道什么东东是JSONP(尽情笑话我吧),只是听我的导师说前端和后台分开放,但是其绑定了不同的子域名,于是需要使用jQuery里面的JSONP支持,给服务端发送请求的时候给一个callback=?参数,然后返回的时候用callback包裹里面的数据。当我看到这篇关于[跨域JSON请求](http://www.ibm.com/develope...

  • 最新评论

  • 标签

  • 最新日志

  • 随机日志

  • 链接

  • 存档

  • 订阅Rss
    Powered by emlog 京ICP备16017775