• FRONT-END

    GET

    POST

    COOKIE

    LOCALE STORAGE

    APPLICATION CACHE

    BACK-END

    DATABASE

    SESSION

    [ 阅读全文 ] 2011-07-14 05:46:38
  • undefined 用于表示一个没有赋值的变量 用于区分改变量是否被赋过值,一个变量在声明的时候默认就是undefined 正常情况下我们不需要手动把一个变量赋值为undefined。

    在变量被声明且没有赋值时,可以访问该变量,始终返回undefined;
    而尝试访问没有声明过的变量则会抛出错误,没有声明的变量唯一能操作的是typeof,返回结果仍然是undefined。

    null则被用于对象的空指针来对待,当一个变量被赋值为null时则认为改变量所持有的是一个对象。
    从typeof null 返回object可以得知,将变量赋值null是对持有对象的变量的一种初始化,为这个对象接下来持有一个对象的引用做初始化。

    NaN是对准备存放数值的变量进行初始化;typeof NaN的到的是number。

    从上得知我们应该养成初始化变量的好习惯,这样在typeof返回undefined时我们就可以确定这个变量没有声明过。
    [ 阅读全文 ] 2011-06-26 02:56:18
  • 关于Ajax应用前进后退操作历史记录目前在很多主流框架例如YUI/Dojo/Prototype/JQuery都已经有比较完美的解决方案。

    但想要实现历史记录的功能都是无法脱离框架的束缚,HashManager是一个脱离所有框架的一个工具类,它不依赖任何框架实现了Ajax应用前进后退功能,并支持AJAX应用的书签访问。

    [ 阅读全文 ] 2011-04-21 06:18:51
  • 越来越习惯在代码里以注解的形式来阐述一些事情了,感觉这样会描述的更清晰一些。

    // 代码没多少废话很多,看下去要有心理准备
    // 原型继承的核心方法
    function clone(obj) {
    	function F () {};
    	F.prototype = obj;
    	return new F();
    }
    
    // Person 类
    var Person = {
    	name: 'default name',
    	getName: function() {
    		return this.name;
    	}
    };
    
    (function (){
    	/* 
    	 * 我们先不看继承,先看看
    	 * 如何实例化一个Person
    	 * 使用clone方法来实例化
    	 */
    	var per = clone(Person);
    	// 给这个人取一个名字
    	per.name = 'default name';
    	// 看看这个人的名字
    	console.log(per.getName()); // output: default name
    	
    })();
    
    /* Author extends Person
     * 继承很简单,直接使用clone方法传入
     * 父类对象即可完成继承
     * 现在可以对继承后的Author添加子类特
     * 有的方法或者覆盖父类同名方法
     *
     * 现在一定有点困惑,为什么继承和实例化都是clone方法
     * 在原型继承中继承和实例化其实是一回事,就像一块砖头
     * 拿起来砸人就是凶器,用来盖房子就叫砖头
     * 通常区分它们通过接收clone返回值的变量名称是否首字母
     * 大写为界,大写为继承,小写为实例化ok~
     */
    var Author = clone(Person);
    Author.books = [];
    Author.getBooks = function () {
    	return this.books;
    };
    
    (function () {
    	/*
    	 * 好吧,我们再来尝试实例化一个Author对象
    	 */
    	var auth1 = clone(Author);
    	// 先来给这个作者一些信息
    	auth1.name = 'Xiaoming';
    	auth1.books = ['午夜的花儿为谁开', '夜半敲门声'];
    	// 上面一句话做一个记号,这里会有问题遗留到后面解决
    	// 试验1:检查继承情况是否良好
    	console.log(auth1.getName()); // output: Xiaoming
    	console.log(auth1.getBooks()); // output: ['午夜的花儿为谁开', '夜半敲门声']
    	// 验证ok
    	
    	/* 试验2:
    	 * 我们需要尝试一下现在改变
    	 * 父类Person是否会影响到子类Author的实例
    	 */
    	Person.getSay = function () {
    		console.log('bingo!');
    	};
    	auth1.getSay(); // output: bingo!
    	// 事实说明是会的。这未必是坏事,这是一种灵活,但不要滥用
    })();
    
    /*
     * 上面这个故事中有没有童鞋发现
     * auth1.name = 'Xiaoming' 这行
     * 的name到底是谁的name
     * 由于原型继承机制的特殊性
     * 父类也是一个对象
     * 通常思维name属性是赋值给继承来的name属性
     * 但这里不同,因为clone而来的auth1起初其实根本没有name属性
     * auth1.name = 'Xiaoming'是在auth上增加一个name属性并赋值的
     * 在prototype中的name仍然没有改变依旧是'default name'
     * 导致这种“非对称读写”现象的原因是当读取对象的某个属性时,该对象本身如果不存在该属性
     * Javascript就会自动搜索对象的prototype对象中是否有,如果有则读取,如果
     * 没有则继续向上protoype寻找,直到Object为止
     * JavaScript设计模式中称为“非对称读写”
     * 为了更透彻的阐释,还是看代码说事
     */
     (function() {
    	var authorClone = clone(Author);
    	console.log(authorClone.getName()); // output: default name
    	/* 
    	 * 很好理解,调用getName方法(不解释)
    	 * JavaScript中去找authorClone的name属性
    	 * 没找到,继续查找authorClone.prototype中是否存在
    	 * 找到了,返回该值也就是Person.name的值default name
    	 */
    	 
    	authorClone.name = 'new name';
    	/*
    	 * 这句话中的name需要澄清一下是新建的
    	 * 而不是改变了Person.name的值
    	 * 所以authorClone.prototype中的name还
    	 * 好好的是 default name
    	 * 只是authorClone对象中多了一个
    	 * name 属性值为 new name而已
    	 * 验证一下
    	 */
    	console.log(authorClone.getName()) // output: new name
    	
    	/*
    	 * 接下来尝试通过push方法
    	 * 对authorClone的books增加内容
    	 */
    	authorClone.books.push('new book');
    	/*
    	 * 看似没什么问题,其实问题很严重
    	 * 理解上面那个故事的童鞋已经恍然大悟
    	 * 事实就是new book被push到了Author.books中
    	 * 所有Author的子类和实例都会读取到这个默认值
    	 * 这里不再试验,现在想想上面那个故事中做记号的地方
    	 * auth1.books = [xxx, xxx]; 的写法为什么没问题
    	 * 原因就在这么写就相当于在auth1中增加了books属性的数组
    	 * 而不会影响父类的值,正确的演示
    	 */
    	authorClone.books = [];
    	authorClone.books.push('new book');
    	// 这么做才是正确的 哈哈
     })();
    
    /*
     * 还有一种情况需要注意的是当父类
     * 属性中含有对象时应该如何处理
     * 处理方法类似上面的数组,略有不同
     * 父类属性中的属性
     * 有点绕口,直接看代码
     */
    (function() {
    	// 一个类(很没营养的例子,能说明白就行哈)
    	var CompoundObject = {
    		string1: 'default value',
    		childObject: {
    			bool: true,
    			num: 10
    		}
    	};
    	
    	// 实例化
    	compoundObject = clone(CompoundObject);
    	// 想要改变该实例中childObject中的num属性
    	compoundObject.childObject.num = 5;
    	// oh no~ 不要这样!这样是能改,但会把CompoundObject中的也改了
    	// 这样改的坏处不再赘述,上文已经提到
    	// 同理,我们需要为这个对象创建一个对象
    	compoundObject.childObject = {
    		bool: true,
    		num: 5
    	};
    	// 虽然这样可以完美达成目的,遗憾的是我们需要关注该对象的其他默认值
    	// 这样悲剧就在于我们想改一个值,但要把其他值原样抄过来
    	
    	console.log(compoundObject);
    })();
    
    // 这是JavaScript设计模式中推荐的写法
    (function() {
    	// 更完美一些我们可以这样解决
    	// 看起来是不太优雅,但这是最接近完美的途径
    	var CompoundObject = {};
    	CompoundObject.string1 = 'default value';
    	CompoundObject.createChildObject = function () {
    		return {bool: true, num: 10}
    	};
    	CompoundObject.childObject = CompoundObject.createChildObject();
    	
    	// 实例化
    	var compoundObjectClone = clone(CompoundObject);
    	compoundObjectClone.childObject = CompoundObject.createChildObject();
    	compoundObjectClone.childObject.num = 5;
    	console.log(compoundObjectClone);
    	// 完美达成!
    })();
    // 原型继承的内容在JavaScript设计模式中介绍的基本就这些,我是权当读书笔记了哈,希望能顺道帮助到别人
    

    相关资料:http://javascript.crockford.com/prototypal.html (老道的原型继承启蒙)

    [ 阅读全文 ] 2011-02-08 07:52:41
  • 其余不解释,直接看操作步骤:

    第一步:下载tar包到指定目录
    wget http://www.erikfantasia.com/download/godaddy-svn-1.5.6.tar.gz

    第二步:解压tar包
    tar zxvf godaddy-svn-1.5.6.tar.gz

    第三部:编辑家目录下的.bashrc文件,追加以下两行,注意svn目录位置设置成刚刚解压后的svn目录
    export PATH=$PATH:$HOME/svn/bin
    export LD_LIBRARY_PATH=$HOME/svn/lib

    大功告成!

    参考:http://erikfantasia.wordpress.com/2009/03/18/subversion-on-godaddy-shared-hosting/

    [ 阅读全文 ] 2011-02-07 01:33:54
  • 为啥jslint默认会将下划线的变量列入警告呢?

    原因是道格拉斯不喜欢这么做,很多人都觉得这样有点过于严厉,事实上下划线开头的变量在很多JS类库中都很常见,也没有出过什么问题。
    在ECMA中提到关于下划线和美元符号的用法:

    from ECMA 262, section 7.6:
    This standard specifies one departure from the grammar given in the Unicode standard: The dollar sign ($) and the underscore (_) are permitted anywhere in an identifier. The dollar sign is intended for use only in mechanically generated code.

    美元符号($)与下划线(_)可以出现在标识符的任何位置。美元符号用于动态生成的代码。

    参考

    [ 阅读全文 ] 2011-02-02 08:53:19
  • 公司的台式机已经装成UBUNTU做了私用的开发服务器,一直都不关机,想着能不能装个虚拟机XP然后在上面可以挂点东东,榨干这台工作机的剩余价值。哈哈
    通过NAT创建了一台XP虚拟机,要将这台服务器的3389端口映射到虚拟机上,这样就可以远程桌面登录虚拟机啦。
    VirtualBox下默认是没有设置端口映射的选项的,不像VM那么先进,但在UBUNTU下VB确实比VM速度上跟好一些。
    VirtualBox 3以后都只要执行如下命令即可做端口映射:

    VBoxManage modifyvm "VM name" --natpf1 "guestssh,tcp,,3389,,3389"

    两个逗号没问题,因为这是空的参数,第一个3389为UBUNTU的端口,后者为虚拟机的端口。

    [ 阅读全文 ] 2011-01-30 06:21:46
  • 把代码当作文章看吧,最后由解说继承实现的原理:

    /**
     * 水果类
     * @param color 水果的颜色
     */
    var Fruit = function (color) {
        this._color = color;
    };
    /**
     * 说出水果的颜色
     */
    Fruit.prototype.tellColor = function () {
        console.log('水果颜色:' + this._color);
    };
    
    /**
     * 香蕉类
     *
     * @extends Fruit
     * @param color 香蕉的颜色
     */
    var Banana = function (color) {
        Fruit.call(this, color);
        this.superclass =Fruit.prototype;
    };
    Banana.prototype = new Fruit();
    Banana.prototype.constructor = Banana;
    /**
     * 玩弄水果
     */
    Banana.prototype.play = function (sth) {
        console.log('一根' + this._color + '色的香蕉正在玩弄' + sth + ' - -!');
    };
    
    // 尝试一下 搞根香蕉玩玩
    var banana = new Banana('BLUE');
    banana.tellColor(); // output: 水果颜色:BLUE
    banana.play('它自己的头发'); // output: 一根BLUE色的香蕉正在玩弄它自己的头发 - -!
    
    // 香蕉的继承机制运作正常
    // 再把香蕉细化看看还是否能正常运作
    
    /**
     * 杭州香蕉类
     *
     * @extends Banana
     * @param color
     */
    var HangzhouBanana = function (color) {
        Banana.call(this, color);
        this.superclass = Banana.prototype;
    };
    HangzhouBanana.prototype = new Banana();
    HangzhouBanana.prototype.constructor = HangzhouBanana;
    
    /**
     * 吃东西
     */
    HangzhouBanana.prototype.eat = function (sth) {
        console.log('这只杭州' + this._color + '色的香蕉正在吃' + sth + ' = =!');
    };
    
    /**
     * 玩
     * @override
     */
    HangzhouBanana.prototype.play = function (sth) {
        this.superclass.play.call(this, sth);
        console.log('一根' + this._color + '色的杭州香蕉正在玩弄' + sth + ' 三 三!!!');
    };
    
    // 看看杭州的香蕉是不是真的能吃东西
    var hzBanana = new HangzhouBanana('GREEN');
    hzBanana.tellColor(); // output: 水果颜色:GREEN
    hzBanana.eat('桌子'); // output: 这只杭州GREEN色的香蕉正在吃桌子 = =!
    
    // 杭州香蕉还有一个重写父类的方法play还没有试
    hzBanana.play('另外一根香蕉');
    // output: 一根GREEN色的香蕉正在玩弄另外一根香蕉 - -!
    //         一根GREEN色的杭州香蕉正在玩弄另外一根香蕉 三 三!!!
    // 成功!
    
    // 现在试试instanceof是否能正常运作
    // 关于typeof大家都懂的,比较悲剧都是object暂时没有有效的办法。
    console.log(banana instanceof Banana, banana instanceof Fruit); // output: true true
    console.log(hzBanana instanceof HangzhouBanana, hzBanana instanceof Banana, hzBanana instanceof Fruit); // output: true true true
    

    为了更好的理解继承实现的原理,当用new关键字来实例化香蕉的同时,发生了一系列的操作:

    -首先会在原型链的最前端创建一个空的Object实例;

    -执行构造,将this的引用都指向这个空的对象;

    -通过call将空对象的引用成为父级类的上下文,
    从而可以使这个空对象(this所指的对象)可以粘附父类的属性,
    比如Fruit中的color属性就在此时在空对象中了(这步需要手动来完成)。
    Fruit.call(this, <color>);

    -接下来便是将子类Banana的prototype属性赋值为父类的实例,
    此举意义在于将父类实力对象中的方法属性赋值到子类Banana的prototype中。

    因为整个prototype都被改成了父类,导致prototype的constructor属性为Fruit,而不是子类本身的Banana。
    需要将prototype.constructor改回来。

    解释一下为什么会出现
    this.superclass = Fruit.prototype;

    this.superclass = Banana.prototype;
    两者道理相同,只解释this.superclass = Banana.prototype;
    目的在于保留一份父类方法,以备在子类override父类方法后还可以调用父类方法调用。
    这里出现在HangzhouBanana的override父类的play同名方法中:
    this.superclass.play.call(this, sth);

    参考资料:JavaScript设计模式 继承章节、YUI3中对继承的superclass的用法

    [ 阅读全文 ] 2011-01-29 09:29:53
  • 模拟实现是从“JavaScript设计模式”一书中摘抄下来的,个人认为是个相对比较完美的模拟实现,详细见注释:
     

    /**
     * 定义接口类
     * @param name 接口名称
     * @param methods 字符串方法名为元素的数组对象
     */
    function Interface (name, methods) {
        if (arguments.length != 2) {
            throw new Error("Interface constructor called with " +
                    arguments.length + " arguments, but expected exactly 2.");
        }
    
        this.name = name;
        this.methods = [];
        for (var i = 0, len = methods.length; i < len; i++) {
            if (typeof methods[i] !== 'string') {
                throw new Error("Interface constructor expects method names to be \
                passed in a string.");
            }
            this.methods.push(methods[i]);
        }
    };
    
    /**
     * 接口类静态方法
     * @param object 任何对象
     * @param ... 任意多个接口对象
     */
    Interface.ensureImplements = function (object) {
        if (arguments.length < 2) {
            throw new Error("Function Interface.ensureImplements called with " +
                    arguements.length + "arguemnts, but expected at least 2.");
        }
    
        for (var i = 1, len = arguments.length; i < len; i++) {
            var interface = arguments[i];
            if (interface.constructor !== Interface) {
                throw new Error ("Function Interface.ensureImplements expects arguments \
                two and above to be instance of Interface.");
            }
    
            for (var j = 0, methodLen = interface.methods.length; j < methodLen; j++) {
                var method = interface.methods[j];
                if (!object[method] || typeof object[method] !== 'function') {
                    throw new Error ('dd');
                }
            }
        }
    };
    
    // 定义一个Item接口
    var interface = {};
    interface.Item = new Interface('Item', ['paint', 'destroy']);
    
    var implements = {};
    /**
     * 定义一个Item接口的实现类
     * 实现类中不需要显示说明此类实现了Item接口
     * 检查将在paintItem方法中进行
     * 
     * @param name
     */
    implements.Item = function (name) {
        this.init.apply(this, arguments);
    };
    implements.Item.prototype.init = function (name) {
        this._name = name;
    };
    implements.Item.prototype.__defineSetter__('name', function (name) {
        this._name = name;
    });
    implements.Item.prototype.paint = function () {
        console.log(this._name + ' paint');
    };
    
    // 实例化两个item对象
    var item1 = new implements.Item('item1');
    var item2 = new implements.Item('item2');
    
    /**
     * 定义绘制item方法
     * @param item 实现了Item接口的item对象
     */
    function paintItem(item) {
        // 此处检查是否实现了Item接口
        Interface.ensureImplements(item, interface.Item);
        item.paint();
    }
    
    // 调用绘制方法
    paintItem(item1); // 输出 "item1 paint"
    
    [ 阅读全文 ] 2011-01-29 03:28:45
«首页