运算符的特殊行为

加法运算符:

  • 运算数是NaN、undefined,则结果为NaN
  • Infinity加Infinity,结果为Infinity
  • -Infinity加-Infinity,结果为-Infinity
  • Infinity加-Infinity,结果为NaN

减法运算符:

  • 运算数是NaN、undefined时,结果为NaN
  • Infinity减Infinity,结果为NaN
  • -Infinity减-Infinity,结果为NaN
  • Infinity减-Infinity,结果为Infinity
  • -Infinity减Infinity,结果为-Infinity

乘法运算符:

  • 运算数是NaN,结果为NaN
  • Infinity乘以0,结果为NaN

除法运算符:

  • 运算数是NaN,结果为NaN
  • Infinity除Infinity,结果为NaN
  • 任何数除Infinity,结果为Infinity
  • 0除非无穷大的数(Infinity),结果为是NaN

取模运算符:

  • 运算数是NaN,结果为NaN
  • 除数是0或者被除数是Infinity,结果为NaN
  • Infinity除Infinity,结果为NaN
  • 除数是Infinity,结果为被除数
  • 被除数是0,结果为0

原文链接(36 views)|沙发已被占领(1)

js下的多态

多态性就是多种表现形式,具体来说,可以用”一个对外接口,多个内在实现方法“表示。举一个例子,计算机中的堆栈可以存储各种格式的数据,包括整型,浮点或字符。不管存储的是何种数据,堆栈的算法实现是一样的。针对不同的数据类型,编程人员不必手工选择,只需使用统一接口名,系统可自动选择。 百科链接

我理解了下,js下应该是这样来实现

var Car = function(type){
   return new Car[type]();
}
 
Car.jeep = function(){}
Car.jeep.prototype = {
    showType: function(){
        return "this is jeep";
    }
}
 
Car.bus = function(){}
Car.bus.prototype = {
    showType: function(){
        return "this is bus";
    }
}
 
var jeep = new Car("jeep");
var bus = new Car("bus");
 
jeep.showType(); // this is jeep
 
bus.showType(); // this is bus

不过要是都这么写,可能就累死了,maybe…

原文链接(430 views)|暂无评论(赶紧抢沙发)

jQuery Autocomplete plugin 1.2

修正因网络延迟而导致的显示错误
增加关键词高亮功能
修正了部分代码
使用固定的回调函数

插件代码:

(function($){
	$.tools = $.tools || {version: '1.2'};
	$.tools.suggest = {};
	$.tools.suggest.defaults = {
		url : null,
		params : null,
		delay : 100,
		cache : true,
		formId : '#search_form',
		focus:null
	}
	$.tools.suggest.borderKey = {
		UP: 38,
		DOWN: 40,
		TAB: 9,
		ESC: 27,
		ENTER:13
	}
 
	$.fn.suggest=function(options,fn){
		var options,key = $.tools.suggest.borderKey;
		if($.isFunction(options)){
			fn=options;
			options = $.extend({}, $.tools.suggest.defaults, key);
		}else{
			options = $.extend({}, $.tools.suggest.defaults, key, options);
		}
		return this.each(function(){
			var
				self = $(this),
				url = options.url,
				params = options.params,
				searchUrl = null,
				searchtimer = 0,
				delay = options.delay,
				cache = options.cache,
				formobj = $(options.formId),
				focus = options.focus,
				rebox = $('<ul />').attr("id","suggest"),
				htmlLi = null,
				litop = null,
				lileft = null,
				liwth = null,
				tip = false,
				val = null,
				rlen = null,
				UP = options.UP,
				DOWN = options.DOWN,
				TAB = options.TAB,
				ESC = options.ESC,
				ENTER = options.ENTER,
				index = -1,
				choseKey = null,
				backval = null,
				hidden = false,
				locksuggest = false,
				timer = null
			;
 
			/* 初始化 */
			if(focus){
				self.trigger('focus');
			}
 
			/* 初始化绑定事件 */
			self.bind("focus",function(){
				backval = (backval=$.trim(self.val()))==''?null:backval;	/* 触发焦点时初始化backval的值 */
				getQueue();
			})
			.bind("blur",function(){
				clearQueue();
				hideResult();
			})
			.bind("keydown",function(e){
				switch (e.keyCode){
				case UP:
					clearQueue();
					if($('#suggest').css('display') == 'none'){
						reSet();
						return false;
					}
					index--;
					if(index&lt;0){
						index=Math.abs(rlen)-1;
					}
					changeSelect(index);
					e.preventDefault();
					break;
				case DOWN:
					clearQueue();
					if($('#suggest').css('display') == 'none'){
						reSet();
						return false;
					}
					index++;
					if(index>=rlen){
						index=0;
					}
					changeSelect(index);
					e.preventDefault();
					break;
				case TAB:
					clearQueue();
					hideResult();
					break;
				case ESC:
					clearQueue();
					hideResult();
					e.preventDefault();
					break;
				case ENTER:
					clearQueue();
					break;
				default:
					getQueue();
					break;
				}
			});
 
			// 获取关键词
			function getKey(){
				val = $.trim(self.val());
				if(!!val && val!=backval){	/* 关键词不为空且关键词不重复 */
					backval = val;
					if(cache && !!$.tools.suggest[val]){	/* 如不需要缓存结果,设cache为false */
						index = -1;
						rlen = $.tools.suggest[val][1];
						appendSuggest($.tools.suggest[val][0]);
					}else{
					    $.tools.suggest[val] = ["",0];
						searchurl = url+'?'+$.param(params);
						getResult(searchurl);
					}
				}
				if(!!!val && !hidden){
					hideResult();	/* 如果关键词为空并且层没有隐藏则隐藏提示层 */
				}
			}
 
			/* 获取提示数据 */
			function getResult(searchurl){
				$.ajax({
                                    type: "GET",
                                    url: searchurl,
                                    cache: true,
                                    dataType: "jsonp",
                                    jsonpCallback: "$.fn.suggest.suggetCallback"
                                });
			}
 
			/* 插入提示数据 */
			function appendSuggest(result){
				locksuggest = hidden = false;
				/* 如果检索结果为空,隐藏提示层反之则输出 */
				if(!!result){
					if(!tip){
						litop = self.offset().top+self.outerHeight()-1;
						lileft = self.offset().left;
						liwth = self.outerWidth()-2;
						rebox.css({'position':'absolute','top':litop,'left':lileft,'width':liwth}).html(result).appendTo('body').show();
						tip = true;
					}else{
						rebox.html(result).show();
					}
					rebox.find('li').bind('mouseover',function(){
						locksuggest = true;		/* 锁定提示层 */
						index = $(this).index();
						changeSelect(index,false);
					})
					.bind('click',function(){
						changeSelect(index);
						searchSubmit();
					});
					rebox.bind('mouseout',function(){
						locksuggest = false;	/* 解锁提示层 */
					});
				}else{
					rebox.hide();
				}
			}
 
			/* JSONP 回调函数 */
                        $.fn.suggest.suggetCallback = function(tmp){
				var data = tmp,
			        htmltemp = '',
				htmllen = data.total,
				inputWord = data.kw;
 
				if(htmllen > 0){
				    $.each(data.list,function(i,n){
					    if(n.word != inputWord){
						    htmltemp += '<li data-value="'+n.word+'">'+n.word+'</li>';
					    }
				    });
				    htmltemp = htmltemp.toLocaleLowerCase();
				    var regex = eval("/\>"+inputWord+"/g"); 
				    htmltemp = htmltemp.replace(regex,"><b>"+inputWord+"</b>");
				    $.tools.suggest[inputWord]=[htmltemp,htmllen];
				}
 
				if(self.val() == inputWord){
				    rlen = htmllen;
				    index = -1;
				    appendSuggest(htmltemp);
				}
 
			}
 
			/* 创建队列 */
			function getQueue(){
				var n = $(document).queue("suggest");
				if(n.length < 1){
					$(document).queue("suggest",getQueue);
					getKey();
					timer = setTimeout((function(){
						$(document).dequeue("suggest");
					}),delay);
				}
			}
 
			/* 清除队列 */
			function clearQueue(){
				$(document).clearQueue("suggest");
				clearTimeout(timer);
			}
 
			/* 变更选项 */
			function changeSelect(index,v){
				v=v==false?false:true;
				var obj = rebox.find('li').eq(index);
				rebox.find('li.mo').removeClass('mo');
				obj.addClass("mo");
				if(v){
					choseKey = backval = obj.attr("data-value");
					self.val(choseKey);
				}
			}
 
			/* 重置层 */
			function reSet(){
				if(!!self.val()){
					index = -1;
					$('#suggest').css('display','block');
					rebox.find('li.mo').removeClass('mo');
					rlen = rebox.find('li').size();		/* 根据html结构重新计算提示结果长度 */
				}
			}
 
			/* 隐藏结果层 */
			function hideResult(){
				if(!locksuggest){
					choseKey = backval = null;
					hidden = true;
					rebox.hide();
				}
			}
 
			/*  提交表单 */
			function searchSubmit(){
				self.val(choseKey);
				clearQueue();
				hideResult();
				formobj.submit();
			}
 
		});
	}
})(jQuery);

返回数据格式

$.fn.suggest.suggetCallback({"total":2,"list":[{"id":"8926","word":"ZAMA\u00b7\u54b1\u4eec"},{"id":"44723","word":"ZOBON"}],"kw":"z"})

原文链接(253 views)|评论 (3)

dojo 中对象扩展与原型继承的实现

dojo 是一款优秀的javascript框架,通常我们可以在复杂的企业级应用中看到它的身影。

dojo 提供了两个方法来实现继承 dojo.mixindojo.extend

dojo.mixin 作用在对象上,它负责扩展一个对象
dojo.extend 作用在实例上,他负责扩展实例(本质上是扩展产生实例的类)

而这两个方法的底层实现是dojo._mixin。

因此,我将这一部分抽出,并进行分析。

(function(){
// 创建一个命名空间
var dojo = {};
// 初始化一些变量
var extraNames, extraLen, empty = {};
    // 判断是否为ie浏览器,如果不是则将 dojo._extraNames 设为空数组
    // 如果是则将其设置为["hasOwnProperty", "valueOf", "isPrototypeOf",
    // "propertyIsEnumerable", "toLocaleString", "toString", "constructor"]
    for(var i in {toString: 1}){ extraNames = []; break; }
    dojo._extraNames = extraNames = extraNames || ["hasOwnProperty", "valueOf", "isPrototypeOf",
    "propertyIsEnumerable", "toLocaleString", "toString", "constructor"];
    extraLen = extraNames.length;
 
    dojo._mixin = function(/*Object*/ target, /*Object*/ source){
    var name, s, i;
    // 历遍源对象
    for(name in source){
        // 将源对象中的属性依次赋给s
        s = source[name];
        // 如果目标对象不存在属性name 或者 目标对象中属性name 的值不等于s
        // 同时这个属性不是js Object 对象的保留属性
        if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
            // 更新目标对象
            target[name] = s;
        }
    }
 
    // IE doesn't recognize some custom functions in for..in
    // 如果是ie浏览器 --> dojo._extraNames 数组不为0
    if(extraLen && source){
        for(i = 0; i < extraLen; ++i){
            // 调用数组中的那些方法
            name = extraNames[i];
            s = source[name];
            // 用 dojo._extraNames 中的方法检查是否可将源对象扩展到目标对象中
            if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
                target[name] = s;
            }
        }
    }
 
    return target; // Object
}
 
dojo.mixin = function(/*Object*/obj, /*Object...*/props){
    // 如果目标为空,初始化一个对象
    if(!obj){ obj = {}; }
    // 调用dojo_mixin() 扩展目标对象
    for(var i=1, l=arguments.length; i<l; i++){
        dojo._mixin(obj, arguments[i]);
    }
    return obj; // Object
}
 
dojo.extend = function(/*Object*/ constructor, /*Object...*/ props){
    for(var i=1, l=arguments.length; i<l; i++){
         // 调用dojo_mixin() 扩展构造函数的原型链
        dojo._mixin(constructor.prototype, arguments[i]);
    }
    return constructor; // Object
}
 
window.dojo = dojo;
})();
 
var obj = {
    age: 24
}
 
// 调用 dojo.mixin 方法扩展obj对象
obj = dojo.mixin(obj,{name:"zhangsan"});
 
alert(obj.name + "'s age is " + obj.age == "zhangsan's age is 24");
 
var User = function (){};
 
var obj = new User();
 
// 调用 dojo.extend 方法扩展 User 对象的原型链
User = dojo.extend(User,{
    saybye: function(){
        return "byebye";
    }
});
 
// obj 对象具备了saybye()的方法
alert(obj.saybye() == "byebye");

原文链接(162 views)|暂无评论(赶紧抢沙发)

对象中的公有方法、私有方法、特权方法

了解如何创建一个对象的时候,我们就需要给这个对象增加方法和属性。

在其他的书籍教程中,我们经常看到各种名称的方法,例如静态方法、实例方法等等,开始我查阅的时候就被这些说法搞的稀里糊涂的,于是自己总结了下,若有错误,还请指出。

1、静态方法和属性
静态方法既只允许父类调用,其他的实例均无法访问和调用的方法和属性。

var user = function(age){
    // 变量age 是user对象的私有属性
    var age = age;
}
 
// user.age 是user对象的静态方法
user.age = function(){
    return this.age;
}
 
// 当我们将user对象实例化的时候
// zhangsan 无法使用 user 对象中
// 的 age方法
var zhangsan = new user(18);
 
// 实例中没有继承user对象的age方法
alert(!!zhangsan.age == false);

2、公共方法
公共方法既依此父类生成的所有实例均可以使用的方法。

var user = function(name,age){
    // 公共变量
    this.name = name;
    this.age = age;
}
 
// 公共方法
user.prototype = {
    getInfo: function(){
        return "他的名字叫:" +this.name+ ",他的年龄是:" +this.age;
    }
}
 
// 当我们将user对象实例化的时候
var zhangsan = new user("zhangsan",18);
 
// getInfo() 就是user对象的公共方法 name\age 既user对象的公共变量
alert(zhangsan.getInfo() == "他的名字叫:zhangsan,他的年龄是:18");
alert(zhangsan.name == "zhangsan");
alert(zhangsan.age == 18);

3、私有方法
私有方法是只有父类可以访问的方法和属性,他与静态方法一致,只是表现形式不一样。构造器中的var变量和参数都是私有方法。

var user = function(age){
    // age 是user对象的私有属性
    var age = age;
 
    // getAget 是user对象的私有方法
    function getAge(){
        return age;
    }
}
 
var zhangsan = new user(18);
 
// 实例中不包含user对象的age属性
// 及getAge方法;
alert(zhangsan.age == undefined);
alert(zhangsan.getAge == undefined);

4、特权方法
当父类中的某一个公共方法可获取父类中的私有方法,同时我们无法修改该方法(可以删除、替换),我们称这种方法为特权方法。
可以访问私有方法,并且在公共域中可见的方法称为特权方法。特权方法不可被修改,只能替换或者删除。

var user = function(age){
    // age 是user对象的私有属性
    var age = age;
 
    // 创建一个特权方法用来获取
    // user 对象下的私有属性age
    this.getInfo = function(){
       return age;
    }
}
 
var zhangsan = new user(18);
alert(zhangsan.getInfo() == 18);

参考资料:http://javascript.crockford.com/private.html

原文链接(135 views)|评论 (2)