我知道的JavaScript
http://www.2cto.com/kf/201109/105999.html
1. JavaScript闭包
代码:
view plain
<pre name="code" class="javascript">(function(){
var validator_elements_blur_selector = ‘…’;
var validator_elements_change_selector = ‘…’;
var validator_elements_selector = ‘…’;
//some other codes…
})();
解释:以上代码中的三个变量的作用域就在整个( )之间,外部无法改变这三个变量的值。这样就可以防止第三方代码对自己本身逻辑的侵入。这也是现在很多Js框架常用的自我保护的方法。代码最后的( )是对这个function 执行操作。前面的( )是对function 进行对象化的包装。这样这段逻辑就可以在代码所在的上下文立即执行了。
2. Javascript 数据结构之– Hashtable
代码:
view plain
<pre name="code" class="javascript">function Hashtable() {
this._hashValue= new Object();
this._iCount= 0;
}
Hashtable.prototype.add = function(strKey, value) {
if(typeof (strKey) == "string"){
this._hashValue[strKey]= typeof (value) != "undefined"? value : null;
this._iCount++;
returntrue;
}
else
throw"hash key not allow null!";
}
Hashtable.prototype.get = function (key) {
if (typeof (key)== "string" && this._hashValue[key] != typeof('undefined')) {
returnthis._hashValue[key];
}
if(typeof (key) == "number")
returnthis._getCellByIndex(key);
else
throw"hash value not allow null!";
returnnull;
}
Hashtable.prototype.contain = function(key) {
returnthis.get(key) != null;
}
Hashtable.prototype.findKey = function(iIndex) {
if(typeof (iIndex) == "number")
returnthis._getCellByIndex(iIndex, false);
else
throw"find key parameter must be a number!";
}
Hashtable.prototype.count = function () {
returnthis._iCount;
}
Hashtable.prototype._getCellByIndex = function(iIndex, bIsGetValue) {
vari = 0;
if(bIsGetValue == null) bIsGetValue = true;
for(var key in this._hashValue) {
if(i == iIndex) {
returnbIsGetValue ? this._hashValue[key] : key;
}
i++;
}
returnnull;
}
Hashtable.prototype.remove = function(key) {
for(var strKey in this._hashValue) {
if(key == strKey) {
deletethis._hashValue[key];
this._iCount--;
}
}
}
Hashtable.prototype.clear = function () {
for (var key in this._hashValue) {
delete this._hashValue[key];
}
this._iCount = 0;
}
解释:Hashtable在c#中是最常用的数据结构之一,但在JavaScript 里没有各种数据结构对象。但是我们可以利用动态语言的一些特性来实现一些常用的数据结构和操作,这样可以使一些复杂的代码逻辑更清晰,也更符合面象对象编程所提倡的封装原则。这里其实就是利用JavaScriptObject 对象可以动态添加属性的特性来实现Hashtable, 这里有需要说明的是JavaScript 可以通过for语句来遍历Object中的所有属性。但是这个方法一般情况下应当尽量避免使用,除非你真的知道你的对象中放了些什么。
[By the way]: StringCollection/ArrayList/Stack/Queue等等都可以借鉴这个思路来对JavaScript 进行扩展。
3. JavaScript设计模式(桥接)应用之 – Validation
引子:
首先请各位同学跟我来一起复习设计模式中的桥接模式(Bridge), 废话不多言表直接上图:
在这个设计模式中我们的抽象类和实现类可以各自进行扩展和封装这样就可以对它们进行脱耦, 通过组合来产生很多变化。这种思想也符合“少用继承,多用组合”的设计原则.在桥接模式中我们可以用Abstraction 类来对实现类(ConreteImplementor)和修正抽象化类(RefinedAbstraction)进行桥接。但JavaScript 如何实现桥接呢?Please follow me
代码:
Validation类:
view plain
Validation= {
required: function(elem) {
return!$(elem).val().trim().isNullOrEmpty();
},
email: function(elem) {
returnValidation.regexValidator($(elem).val().trim(),Validation.Regex.email);
},
regexValidator: function(elemVal, /*string*/regex,) {
if(!elemVal.isNullOrEmpty() && !(elemVal.match(regex, "\g"))) {
returnfalse;
} else{
returntrue;
};
},
Regex: {
email:/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)?$/
}
};
Validation.validateColl= {
'jq-validation-required': {validFunc:Validation.required, ErrMsg: 'Required'},
'jq-validation-email': {validFunc:Validation.email, ErrMsg: 'Invalid email address'}
};
Validator类:
view plain
(function () {
varvalidator_elements_blur_selector = 'input[type="text"]';
varvalidator_elements_change_selector = 'select,input[type="hidden"]';
var validator_elements_selector =validator_elements_blur_selector + ',' +validator_elements_change_selector;
Validator = function(validateScopeSelector) {
this._validateColl= $.extend(true, {}, Validation._validateColl);
this._validateDom= $(validateScopeSelector);
vartheValidator = this;
this._validateDom.delegate(validator_elements_blur_selector,'blur',function() {
theValidator.validateInput(this, 'blur');
});
this._validateDom.delegate(validator_elements_change_selector,'change', function() {
varinputValidated = theValidator.validateInput(this,'change');
});
};
Validator.prototype = {
validate: function() {
varvalidated = true;
vartheValidator = this;
$(validator_elements_selector, this._validateDom).each(function() {
if(!theValidator.validateInput.call(theValidator, this)) {
validated = false;
};
});
returnvalidated;
},
validateInput: function(elem, event) {
varinput = $(elem);
varclassArr = input.attr('class').split(' ');
varvalidated = true;
varinValidTable = new Hashtable();
for(var i = 0; i < classArr.length; i++) {
varclassItem = classArr[i];
if(!classItem.startWith('jq-validation')) continue;
varvalidateItem = this._validateColl[classItem];
if(validateItem && validateItem.validFunc) {
if(!validateItem.validFunc(input, validateItem)) {
validated = false;
if (!strPopupErr.isNullOrEmpty()) {
strPopupErr += " ";
}
inValidTable.add(classItem, validateItem);
}
}
}
returnvalidated;
}
};
})();
调用例子:
view plain
<html>
<div id="validation_region">
< input type="text"class="jq-validation-required"/>
< input type="text"class="jq-validation-email"/>
</div>
< input type="button"onclick="submit()"/>
<script language="javascript"type="text/javascript">
var validator = new Validator("#validation_region");
function submit(){
if(validator.validate()){
alert('验证通过!');
}else{
alert('验证失败!');
}
}
</script>
</html>
view plain
<pre>
解释:
1.设计思想
其中Validation 可以定义和扩展各种验证规则的方法,而Validator则负责处理验证后的错误提示以及如何正确反馈给代码调用者是否验证通过, Validation.validateColl则定义了哪种类型的验证调用哪一个验证规则的处理方法,他们各自分工明确,这也符合单一职责的设计原则。以上代码中我们可以看到Validation 对象是实现类,而Validator 对象是修正抽象化类, 而Validation.validateColl则是桥接器(在经典的Gof 23模式中没有这个定义)。当然在这里我们已经不能完全按照设计模式中定义的术语来描述以上代码了。我们只是按照设计模式的思路和理念来设计和构造我们的代码。
2.工作原理
在调用的例子中:
var validator = newValidator("#validation_region");
当页面加载完成后我们首先实例化Validator对象并传入需要验证的范围(Scope), 在这里我们传入需要验证区域的ID, 我们利用jQuery的$() 方法来把选择符“#validation_region"转换成可操作的DOM对象.
当Button 点击时我们调用submit方法,这时执行validator.validate 方法,这个方法会利用jQuery的each方法遍历验证范围内的所有input 控件进行验证,并最终返回验证的结果。
在Validate的内部方法中我们还可以加入当验证未通过时对input 进行改变样式并错误提示的功能,一般作法是在input加上红色的边框以提示用户,在这里这个功能需要读者根据项目的需求自己进行扩展了.
3.扩展验证规则
前面我们讲解了设计思想以及工作原理,那么我们如何对validation 进行扩展呢?
我们只需要增加新的验证规则方法到Validation对象上,并在Validation.validateColl 对验证类型(input 的class 名)和新的验证规则进行桥接。
例如:
如果我们要加入一个验证是否是数字的规则,我们需要在Validation 对象中加入
number:function (elem) {
return!isNaN($(elem).val());
}
并在Validation.validateColl中加入
'jq-validation-number': { validFunc:Validation.number, ErrMsg: 'Notnumber’ }
这时我们并不需要更改任何Validator的代码就可以在input 的class中加入’jq-validation-number’ 来进行数字规则验证了。
这里需要说明一点如果需要对一个input 进行多种验证规则可以在class中以空格分割写入多种验证规则的名称
例如:
<input type="text" class="jq-validation-requiredjq-validation-number"/>
4. 在Asp.net mvc 下Json对象转换(扁平化)
------------ 解决Ajax无法提交复杂Json数据到Action 的问题
引子:
在Asp.net mvc 框架下当提交一个表单到Action方法上。可以把表单中的数据自动绑定到Action方法上参数的对象上,用Ajax 方法调用Action时当需要提交一个复杂对象如以下对象结构:
view plain
{
hotelName:’abc’,
hotelAddress:’ 北京海淀路72号’,
Rooms:[ {roomName:’标准间’,roomPrice:720},
{roomName:豪华间,roomPrice:1020}],
HotelStar:4
}
这时我们必需转换成如下格式才能正确提交到后台Action的对象上。
view plain
{
hotelName:’abc’,
hotelAddress:’ 北京海淀路72号’,
Rooms[0]: {roomName:’标准间’,roomPrice:720},
Rooms[1]: {roomName:豪华间,roomPrice:1020},
HotelStar:4
}
代码:
view plain
Convert={
_jsonFlat:function (data, parentPro, returnObj) {
if (data instanceof Object) {
for (varpro in data) {
try{
varproValue = eval("data." +pro.toString());
if(proValue instanceof Array) {
for (var i = 0; i <proValue.length; i++) {
if (parentPro){
Convert._jsonFlat(proValue[i], parentPro + "." + pro + "["+ i + "]", returnObj);
}
else
Convert._jsonFlat(proValue[i], pro + "[" + i + "]",returnObj);
}
continue;
}
if(proValue instanceof Object) {
if(parentPro)
Convert._jsonFlat(proValue, parentPro + "."+ pro, returnObj);
else
Convert._jsonFlat(proValue, pro, returnObj);
continue;
}
if(parentPro)
returnObj[parentPro + "." + pro] = proValue;
else
returnObj[pro] =proValue;
}
catch(e) { };
}
return;
}
//otherwiselike string/int/datetime format
returnObj[parentPro] = data;
},jsonFlat: function(data) {
//debugger;
if(data && data instanceof Object) {
varretObj = {};
Convert._jsonFlat(data, null, retObj);
returnretObj;
}
return null;
},
}
解释:以上代码就是完成Json对象格式的转换。只有通过转换后的复杂Json对象才能提交到后台的Action 方法上。JsonFloat方法运用递归遍历json对象上的所有属性进行转换。
作者“bingbing200x的专栏”