没空讲原理了,写了一个DEMO供大家学习,先上一段核心代码,然后附上DEMO。
请查看DEMO,更详细的理解Observer(观察者)模式
DEMO:test.html
function ObserverList(){
this.observerList = [];
};
ObserverList.prototype.Add = function(obj){
if(this.IndexOf(obj,0)==-1){
return this.observerList.push(obj);
}else{
this.observerList;
}
};
ObserverList.prototype.Empty = function(){
this.observerList = [];
};
ObserverList.prototype.Count = function(){
return this.observerList.length;
};
ObserverList.prototype.Get = function(index){
if(index>-1 && index<this.observerList.length){
return this.observerList[index];
}
};
ObserverList.prototype.Insert = function(obj,index){
var pointer = -1;
if(index===0){
this.observerList.unshift(obj);
pointer = index;
}else if(index === this.observerList.length){
this.observerList.push(obj);
pointer = index;
}
return pointer;
};
ObserverList.prototype.IndexOf = function(obj,startIndex){
var i = startIndex,pointer = -1;
while(i<this.observerList.length){
if(this.observerList[i]===obj){
pointer = i;
}
i++;
}
return pointer;
};
ObserverList.prototype.RemoveIndexAt = function(index){
if(index===0){
this.observerList.shift();
}else if(index===this.observerList.length-1){
this.observerList.pop();
}else{
this.observerList.splice(index,1);
}
}
function extend(obj,extension){
for(var key in obj){
extension[key] = obj[key];
}
}
function Subject(){
this.observers = new ObserverList();
}
Subject.prototype.AddObserver = function(observer){
this.observers.Add(observer);
};
Subject.prototype.RemoveObserver = function(observer){
this.observers.RemoveIndexAt(this.observers.IndexOf(observer,0));
console.log(this.observers);
};
Subject.prototype.Notify = function(context){
var observerCount = this.observers.Count();
for(var i=0;i<observerCount;i++){
this.observers.Get(i).Update(context);
}
};
Read more »
JS发布后通常会经过压缩和混淆,所有代码被压缩成一行代码,如果发生错误,无法定位错误,SourceMap因此而生。
说起SourceMap,不得不说说uglifyjs,uglifyjs是nodejs下一款优秀的JS压缩优化工具,支持SourceMap的生成。
一、uglifyjs的使用及SourceMap文件的生成方法
1、安装nodejs:http://nodejs.org,windows下直接安装即可,安装好后自带npm.
2、打开CMD,输入node -v查看,nodejs是否安装成功,如果成功会返回一个版本号。
3、安装uglifyjs:执行命令:npm install uglify-js -g
4、uglifyjs使用方法及API:https://github.com/mishoo/UglifyJS2
5、压缩JS并生成SourceMap文件
uglifyjs underscore.js --source-map underscore.js.map
--source-map-root ./ -m -c -o underscore-mini.js
会生成两个文件:
- underscore-mini.js(压缩文件)
- underscore.js.map(SourceMap文件)
二、用 SourceMap 调试
有了SourceMap文件,放置underscore-mini.js同一目录,引用underscore-mini.js时,就可以调试,看到未压缩的代码
调试方法:
打开chrome – F12(打开调试工具)- 调试工具右下角有一个设置,打开设置 – General – Enable source maps
这样就打开了SourceMap调试功能。
在Sources面板下,左侧展开,就能看到SourceMap解出来的未压缩文件,多个压缩文件都可以看到。
三、SourceMap的原理解析
单说,Source map就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应的转换前的位置。有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码。这无疑给开发者带来了很大方便。
1、SourceMap基本结构如下:
/assets/upload/20130723160149.png
- version:Source map的版本,目前为3。
- file:转换后的文件名。
- sourceRoot:转换前的文件所在的目录。如果与转换前的文件在同一目录,该项为空。
- sources:转换前的文件。该项是一个数组,表示可能存在多个文件合并。
- names:转换前的所有变量名和属性名。
- mappings:记录位置信息的字符串,下文详细介绍。
2、重点在于mappings的解码
第一层是行对应,以分号(;)表示,每个分号对应一行代码;
第二层是位置对应,以逗号(,)表示,每个逗号对应转换后源码的一个位置。
第三层是位置转换,以VLQ编码表示,代表该位置对应的转换前的源码位置。
VLQ编码相关,请查询更多资料~~
Read more »
jQuery作为前端最流行的类库,没有之一,源码必须得读一读。本博将不定期更新源码解读内容,如果解读不正确的地方,还请同学们在评论中指正。
本系列文章基于最新的jquery-1.9.1.js。
一、$.type() 判断js数据类型
用法:$.type(new Array()); //array
部份源码(截取关键部份,请忽略源码语法):
class2type = {}
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
core_toString = class2type.toString
type: function( obj ) {
if ( obj == null ) {
return String( obj );
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[ core_toString.call(obj) ] || "object" :
typeof obj;
}
解读:
1、class2type生成后的内容为
var class2type = {
"[object Boolean]":"boolean",
"[object Number]":"number",
"[object String]":"string",
"[object Function]":"function",
"[object Array]":"array",
"[object Date]":"date",
"[object RegExp]":"regexp",
"[object Object]":"object",
"[object Error]":"error"
}
2、core_toString使用的是对象实例的toString
所有继随自Object的对象都有toString方法,为什么一定要使用object.toString,因为array,function虽然有toString方法,但该方法进行了重写,array调用toString打印的数组成员用逗号隔开的字符串。这里使用的是{}.toString.call(obj);改变toString的this指向为object实例。jquery为什么使用的是class2type.toString.call,这样就可以少声明一个object。
var func = function(){};
var arr = [];
console.log({}.toString.call(func));
console.log({}.toString.call(arr));
这样就得到class2type的键名,以此判断数据类型。
Read more »
在工作中,常碰到模态窗口、固定header、固定广告、固定go to top等等,都需要一个很重要的特性position:fixed,该特性在大多数浏览器下支持的还不错,只有IE6这个老大难,又调皮了。
遇到问题就解决问题,解决了问题就记录下,趁假期得空,把一些遇到的坑填平记录一下,同时分享给各位同学,好了,不多废话。
一、IE6下使用position:absolute代替position:fixed
使用绝对定位,很好理解,但是浏览器在调整时(滚动、缩放),left和top如何动态的计算其值呢?在IE6下CSS表达式(expression)可以帮我们解决难题,虽然IE8取消了该API,由于其它效率低,不建议使用。浏览器在调整时,会重新计算css expression,所以我们的问题就解决了。
CSS解决办法:
* html .header{
position:absolute;
left:expression(eval(document.documentElement.scrollLeft+10)+"px");
top:expression(eval(document.documentElement.scrollTop+10)+"px");
}
JS解决办法:
expression对应在JS中的方法是style的setExpression方法,第一个参数是CSS属性名,第二个参数计算表达式字符串。
domThis.style.setExpression('left',
'eval((document.documentElement).scrollLeft + ' + 10 + ') + "px"');
二、修正IE6抖动bug
IE有一个多步的渲染进程。当你滚动或调整你的浏览器大小的时候,它将重置所有内容并重画页面,这个时候它就会重新处理css表达式。
因此虽然CSS进行了重新计算,需要fixed的元素位置也进行了正确的调整,但是会有一跳一跳的抖动感觉,这种体验很不好,如果浏览器调整的频繁,很伤眼。
好在,这个问题不是无解的,是“有药可医”的。
Read more »
一、IE6下使用form post target iframe进行POST跨域请求,如果设置了document.domain,POST请求发送不出去。
另外iframe的name属性要一次性写入,不能通过dom的方式修改,修改无效。
www.2fz1.com/a.html
<script type="text/javascript">
document.domain = "2fz1.com"
</script>
<iframe name="commentpost" id="commentpost"></iframe>
<form action="http://data.2fz1.com/data.php" method="post" target="commentpost">
<textarea name="detail"></textarea>
<input type="submit" class="publish_btn" value="提交">
</form>
原因分析:
1、IE6下,因为在父页面或在iframe页面中,只要设置了document.domain,无论是和当前域名相同还是根域名,均视为跨域。而我们使用form post到iframe时,IE6当作跨域给“拒绝访问”了。有人可能会说,可以给子页面设置document.domain,但是我们的子页面是变动的服务器程序,iframe的src如果是定死的就可以解决。
2、大概定位一下:IE6升级到IE7后默认禁用了“跨域浏览子框架”,但是IE7下不会禁用这种,但是把IE7卸载后回到ie6这个设置没改回原来默认的启用,导致ie6不允许form.target指向一个空的iframe。IETester下的IE6,也有同样的原因。
解决办法:
<iframe src="javascript:document.domain='xxx.ooo';void 0;"></iframe>
Read more »
html{
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: grayscale(100%);
filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/
svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333
0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1
0\'/></filter></svg>#grayscale");
filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
}
不过对firefox和flash支持不好,暂时没有总结出最完美的兼容方案。
Read more »
由于JS是单线程语言,程序在同步执行时,如果耗时较长就会阻塞下面的进程,而异步编程则可以避免这个问题。异步编程在耗时长的操作中非常重要,比如连接网络文件,读取本地文件等。
Ajax就是经典的异步程序,但是多个ajax需要串行执行时,怎样才能优雅有序的执行呢?本文将探讨大规模异步ajax串行执行时的编程问题。
常用的几种异步编程方式有:【本文代码范例基于jquery】
一、回调函数
function a(callback){
$.get("a.php",function(data){
callback(data);
});
}
function b(data){
console.log(data);
}
a(b);
a执行完后,b再执行。这是典型的回调函数用法,但是回调函数代码高度耦合,代码可读性不高,而且比较混乱,如果回调流程比较长,需要从中减掉一个回调流程时,不易修改。
Read more »
jQuery在1.5开始引入deferred(延迟),简单说,deferred对象就是jQuery的回调函数解决方案。
jQuery1.5中,Deferred对象提供一种方式来注册多个回调,添加到自已管理的回调队列中,调用适当的回调队列,并转达同步或异步函数的成功或失败状态。
deferred对象有三种执行状态:未完成(pending),已完成(resolved)和已失败(rejected)
API概览:
deferred object = {
always(alwaysCallbacks [, alwaysCallbacks])
done(doneCallbacks)
fail(failCallbacks)
isRejected()
isResolved()
notify( args )
notifyWith(context, [args])
pipe([doneFilter] [, failFilter] [, progressFilter] )
progress( progressCallbacks )
reject([args])
rejectWith(context, [args])
resolve([args])
resolveWith(context, [args])
state()
then(doneCallbacks, failCallbacks [, progressCallbacks])
promise([target])
}
Read more »
配置如下hosts:
207.97.227.239 github.com
65.74.177.129 www.github.com
207.97.227.252 nodeload.github.com
207.97.227.243 raw.github.com
204.232.175.78 documentcloud.github.com
204.232.175.78 pages.github.com
Read more »
二分之一前端开发,经过周末两天的奋战,我的博客(2fz1.com)一年后终于换肤了,新主题命名“Butterfly”(蝴蝶),颜色选择有点丰富,一改去年的简朴,最大的特色是图标字体化,预计会加上更多的html5+css3应用。演示:
http://www.2fz1.com
Read more »