2011年5月20日
我们知道,js的数组具有一个sort方法,这个sort方法还可以传入一个特定形式的比较函数进行自定义排序,它的用法类似这样:
[5,4,9,2,7].sort(function(a,b){return(a-b);});
这个特定形式的自定义比较函数,要求有两个参数,通常情况下,函数的内容是两个参数本身或其属性的对比,该函数的返回值必须为负数、0和正数之一。另外sort函数会改变数组,而不是返回一个新的数组。
最近我的一段js代码使用了js数组的自定义排序,在ie8和ff4下正常,然而在ie6和ie7下报“缺少数字”错误,经过研究发现,是自定义比较函数的返回值出现了NaN这个非数字造成的,这种情况下,ie6和ie7直接报错,而ie8和ff4不会报错,如下的代码可以可以重现这个问题:
var arr = [
{o:3,toString:function(){return this.o}},
{o:undefined,toString:function(){return this.o}},
{o:4,toString:function(){return this.o}},
{o:1,toString:function(){return this.o}}
];
arr.sort(function(a,b){return a.o-b.o;});//使用元素的o属性进行比较
debug.innerHTML=arr;
由于数组arr中有一个元素的o属性没有定义,因此比较函数中会出现数字与undefined相减的情况,结果就是NaN,于是ie6和ie7报错了,截图如下:

解决这个问题的办法,就是避免自定义比较函数返回非数字。但是ie8为什么不报错呢?难道ie8下传给sort函数的比较函数返回NaN不抱错吗?答案是肯定的,当比较函数的返回值为NaN的话,ie8不会报错,但是排序结果会发生一些不可预料的变化,上面同样的代码,在ie8下的结果是:
这个结果令我疑惑,如果把arr改成:
var arr = [
{o:3,toString:function(){return this.o}},
{o:6,toString:function(){return this.o}},
{o:undefined,toString:function(){return this.o}},
{o:4,toString:function(){return this.o}},
{o:1,toString:function(){return this.o}}
];
则排序后结果是:
如果我把o属性未定义的元素移到o属性为3的元素下面,则返回结果是:
这正是我的疑惑,如果你知道答案,请不吝赐教。
那么ie8的sort的自定义比较函数是不是无论返回什么都不报错呢?答案是否定的,如果我把比较函数的返回值硬编码成“return “#@#@””,则ie8也报错了:
因此,我认为ie8的的sort函数,相比IE6和ie7,至少进行了体验上的优化,即如果发现自定义比较函数的返回值是NaN,则不报错,只是排序可能会出现非预期的结果而已,但是如果返回值是字符串,则将严惩不贷,弹出令人震惊的错误框。
2009年10月31日
关于视野,我以前就有很多想法,因为我经常由于视野不宽而走弯路,因此觉得视野太重要了,比智商和技术更重要。
我以前做ajax应用的时候不知何为异步何为同步,更不知何为回调,总觉得程序应该是一条一条执行下去的,上一语句还在执行的时候不可能会执行下一语句的,因此在写xmlhttp的时候,总是不知道把async属性设为true,而是按部就班地先发出请求,然后等待返回的结果,当时还纳闷说,ajax这么流行的东西怎么这么卡呢?后来深入了解ajax之后就知道,使用同步模式,只要你的请求还没被返回,你就要一直等待,这段时间你的鼠标不能动,滚动条不能动,也就是“阻塞”了,能不觉得“卡”吗!
当时只从书上知道xml是国际通用数据交换格式,因此用xml交换数据,把数据库的记录转换成xml,再发到客户端,客户端用xmldom去解析,现在才知道相对于json,这是多么笨拙和缓慢的办法,如果早点了解ORM,了解json序列化,以后又怎么会再花大力气去重构以前那些丑陋的应用。
还有些其他人的例子,比如我有个同事,为了让用户关闭浏览器就会话失效,打算把项目从cookie存储身份信息换成session,而事实上只需把form验证的某个配置改为false即可,如果身边没有同事告知,多少的劳动力又浪费在这些弯路上了?
刚才还看到一片博文,博主说看到某C#函数中的参数前有this关键字,于是百思不得其解,便做了个小程序去测试,百转千回终于发现那个类下面多了这个方法,事实上这就是C# 3.0中新增的“扩展方法”机制,如果博主在一两年前C# 3.0发布的时候稍微了解下这些新特性,又何必对这个参数前的this大惊小怪,不过本人非常敬佩该博主的专研精神和工作学习的态度。
技术可以让您做出来,比如做聊天室,视野窄的用定时刷新页面,稍好点的会用ajax轮询,而视野更广的会用comet长轮询,技术是实现了,但是视野的宽度决定了产品是否具有先进,越有先进性,那么被淘汰的概率也小,而那些因为视野窄而使用并不优越的方法做出来的东西,不但以后可能要重构,还可能被淘汰。
视野的建立不是一蹴而就的,相反正是在缺乏视野的跌跌撞撞中才会扩大人的视野,有的人接触的东西少,想依赖实践去扩大视野显然是相当慢的,因此就要多多学习了,我以上举的几个例子,如果主人公在实践之前就掌握了扎实的WEB编程理论知识,就会少走许多弯路。
千言万语汇成一句话,没事多学学,多去技术社区看看,多去英文网站看看,多关注下新技术、新动态,当你的精力有限时,不必了解某种技术具体怎么去用,但是应该了解这种技术有什么优点和缺点,适应什么场合。
2009年8月15日
前言:网上有不少文章是讲行转列的,但是大部分都是直接贴代码,忽视了中间过程,本人自己思考了下为什么要这样实现,并且做了如下的笔记,对有些懂的人来说可能没有价值,希望对还不懂的人有一点借鉴意义。
对于有些业务来说,数据在表中的存储和其最终的Grid表现恰好相当于把源表倒转,那么这个时候我们就碰到了如何把行转化为列的问题,为了简化问题,我们且看如下查询出来的数据,您不必关心表的设计以及sql语句:
假设用到的sql语句为:
SELECT [姓名],[时代],[金钱]
FROM [test].[dbo].[people]
这个表存储了两个人在不同时代(时代是固定的三个:年轻、中年和老年)拥有的金币,其中:
张三在年轻、中年和老年时期分别拥有1000、5000、800个金币;
李四在年轻、中年和老年时期分别拥有1200、6000、500个金币。
现在我们想把两人在不同阶段拥有的金币用类似如下的表格来展现:
| 姓名 |
年轻 |
中年 |
老年 |
| 张三 |
1000 |
5000 |
800 |
| 李四 |
1200 |
6000 |
500 |
我们现在考虑用最简单和直接的办法来实现,其实关键是如何创建那些需要增加的列,且如何设定其值,现在我们来创建“年轻”列,关键的问题是,这一列的值如何设定?合法的逻辑应该是这样:如果该行不是“年轻”时代,那么其“金钱”我们认为是0,那么sql语句如何写呢?
如果是用的sql server,那么肯定要用到case了:
case [时代] when '年轻' then [金钱] else 0 end as 年轻
或
case when [时代]= '年轻' then [金钱] else 0 end as 年轻
如果用的是oracle,那么要用到decode函数,decode(1+1,3,'错',2,'是',5,'错','都不满足下返回的值'),这个函数将返回“是”,具体用法限于篇幅这里不再介绍,相信大家从这个式子可以大概了解到其意思,用decode创建“年轻”列的句子是:完整的sql语句如下所示:
decode(时代,'年轻',金钱,0)) 年轻
SELECT [姓名],[时代],[金钱],
case [时代] when '年轻' then [金钱] else 0 end as 年轻,
case [时代] when '中年' then [金钱] else 0 end as 中年,
case [时代] when '老年' then [金钱] else 0 end as 老年
FROM [test].[dbo].[people]
现在我们来看看其执行结果:
相信看到这个结果,大家都知道下一步该做什么,那就是分组:按姓名分组,并且对三个时代的金钱进行求和:
select [姓名],sum([年轻]) as 年轻,sum([中年]) as 中年,sum([老年]) as 老年 from
(SELECT [姓名],[时代],[金钱],
case [时代] when '年轻' then [金钱] else 0 end as 年轻,
case [时代] when '中年' then [金钱] else 0 end as 中年,
case [时代] when '老年' then [金钱] else 0 end as 老年
FROM [test].[dbo].[people]) t
group by [姓名]
这里用到了子查询,是为了逻辑更清晰一点,其实可以不用子查询;至于oracle下的sql语句,除了要使用decode之外,其余几乎一致,本人正是在oracle中实现之后才研究了下sql server下的实现方式。
最后看看结果:
事实上,当列不固定的时候,比如除了“年轻”、“中年”、“老年”以外还有其他的未知的时代,实现思路其实基本一致,只是需要动态生成sql而已。
2009年7月13日
自从CSS出现以来,就有厂商希望CSS能够更加灵活一点,最早的CSS动态化体现为“动态表达式”(或动态属性,Dynamic attribute)的构想,动态表达式的构想也许是源自于以下的一些场景:
- 元素的尺寸或者位置由浏览器或者html文档来计算
- 使用变量作为style属性的值,比如频繁使用的颜色,用一个全局变量
包括浏览器的鼻祖Netscape以及IE浏览器都试图在CSS中使用javascript,Netscape公司在很久很久以前提出了JSS技术,当然只支持Netscape浏览器:
“JavaScript Style Sheets. In the beginning, they were JASS (JavaScript Accessible Style Sheets), then JSSS or JSS (JavaScript Style Sheets), and now Netscape has taken to calling them Style Sheets with JavaScript Syntax. They exist in the Netscape DHTML documentation, a few books, and a couple of old third party articles on the web. The best introduction to JSS is by HTML veteran Chuck Musciano, at SunWorld. A concise, clear examination, this article was written a year ago (April 1997). Next to nothing has been written on the Web since then。”
一段经典的Netscape浏览器的JSS代码如下所示:
<STYLE TYPE='text/javascript'>
with (parent.frames.main.document.classes.items.SPAN) {
width = menuWidth;
color = fntCol;
fontSize = fntSiz;
fontWeight = fntWgh;
fontStyle = fntSty;
fontFamily = fntFam;
borderWidth = borWid;
borderColor = borCol;
borderStyle = borSty;
lineHeight = linHgt;
}
</STYLE>
微软公司在IE5之后提出了“动态属性(Dynamic Properties)”技术:
“IE5及其以后版本支持在CSS中使用expression,用来把CSS属性和Javas cript表达式关联起来,这里的CSS属性可以是元素固有的属性,也可以是自定义属性。就是说CSS属性后面可以是一段Javas cript表达式,CSS属性的值等于Javas cript表达式计算的结果。 在表达式中可以直接引用元素自身的属性和方法,也可以使用其他浏览器对象。这个表达式就好像是在这个元素的一个成员函数中一样。 ”
一段经典的CSS Expression代码如下:
#myDiv
{
position: absolute;
width: 100px;
height: 100px;
left: expression(document.body.offsetWidth - 110 + "px");
top: expression(document.body.offsetHeight - 110 + "px");
background: red;
}
ie的动态表达式出现的时候,引起不少web开发者的狂欢,但是时隔不久,其卑劣的性能开始引起人们的诟病,据称,动态表达式在DOM发生更新的那一瞬间居然执行了上万次,另外由于与web标准的不兼容,CSS Expression几乎已经被日益追求潮流的web开发者所摈弃。
至此,两大浏览器的巨头都终止了在CSS中使用Javascript的妄想,但是CSS混javascript的灭亡只是浏览器大战以及自定标准与W3C标准竞争的牺牲品而已。
为什么一些狂热的程序员会对基于javascript的css乐此不疲呢?笔者认为主要有以下两个原因:
- 1、CSS本身的静态特性
- 2、W3C标准与浏览器版本不能也永远不能同步的矛盾
- 3、html开发人员的期望与W3C标准不能也永远不能同步的矛盾
html的CSS技术本身的缺点已经引起了软件开发巨头的注意,在当前狂躁的应用程序标记语言中,比如微软的XAML或adobe的MXML,其CSS(暂且称之为CSS吧)不仅可以动态定义,甚至还可以定义属性、内容和事件。也许,在几年之后,我们将看到W3C准备修正新的CSS标准,让其更加动态化。
2009年5月30日
这篇文章是续《小巧优美的ORM框架-doodads入门指南》的,在上篇文章,我讨论了喜爱doodads的理由:
- 轻巧,部署简单,文件少且小,开源免费
- 简单,不支持关系映射,不支持多表操作,所有的实现必须您亲自写sql或建立视图来实现
- 依赖存储过程,间接地提高性能
不过,其官方网站宣称已经不再维护doodads了,尽管如此,如果您发现您的项目适合doodads而你暂时又没有找到其他的框架,另外学习时间有限的话,使用doodads貌似不会令您失望。
以下的文章给出了doodads和一些其他ORM框架的比较: 《SubSonic v1 (ActionPack) vs dOOdads vs Castle ActiveRecord》
另外有人提出doodads究竟是不是ORM,这个问题确实难倒我了,事实上我连ORM的具体定义是什么也不清楚,这个问题还是留给对ORM有很深研究以及应用的老鸟吧!
接下来进入正题:
doodads的基本CRUD操作
首先您需要保证已经创建了一个表对象:
-----------------------------------------
Employees emps = new Employees();
-----------------------------------------
1、根据主键获取单条记录(PS:doodads获得的记录是存储在datatable中的):
-----------------------------------------
emps.LoadByPrimaryKey(123);
//然后使用“emps.字段名”即可获取该记录的字段值
-----------------------------------------
2、获取所有记录(准确说是获取所有符合条件的记录,如果指定了where等参数)
-----------------------------------------
emps.LoadAll();
//然后使用"emps.DefaultView"可以得到数据源DataView
//使用"emps.Query.ReturnReader() as SqlDataReader"得到DataReader
//使用"emps.RowCount”可以得到记录的条数
-----------------------------------------
3、创建记录
-----------------------------------------
emps.AddNew();
emps.LastName = "Smith";
emps.HireDate = DateTime.Now;
emps.Save();
empID = emps.EmployeeID; //得到了新纪录的主键
-----------------------------------------
3、修改记录(ps:生成的sql只更新您修改过的字段,不会更新所有字段)
-----------------------------------------
emps.LoadByPrimaryKey(123); //先加载要修改的记录
emps.LastName = "Jones"; //修改某字段
emps.Save(); //保存
-----------------------------------------
4、删除记录
-----------------------------------------
//之前您应该加载了某条记录,或者游标置在某条记录
emps.MarkAsDeleted(); //将当前的记录置为删除
emps.Save(); //保存
-----------------------------------------
5、遍历所有已加载的记录(ps:您也可以遍历"emps.Query.ReturnReader() ")
-----------------------------------------
if(emps.RowCount > 0)
{
emps.Rewind(); //光标置为第一条
do
{
//这里可以操作当前的记录,比如读字段值、修改、删除
} while(emps.MoveNext());
}
-----------------------------------------
6、动态查询
动态查询可以让您不需要手写sql就获取到需要的记录,并且可以设置排序以及限定选择的列,还有效地预防了手写sql带来的sql注入隐患。
doodads的WhereParameter枚举提供了如下的连接符、排序方向和运算符:
连接符(WhereParameter.Conj)
• And
• Or
• UseDefault
排序方向 (WhereParameter.Dir)
• ASC
• DESC
运算符 (WhereParameter.Operand)
• Between
• Equal
• GreaterThan
• GreaterThanOrEqual
• In
• IsNotNull
• IsNull
• LessThan
• LessThanOrEqual
• Like
• NotEqual
• NotIn
• NotLike
如下的例子给出了如何灵活运用WhereParameter和Query查询数据:
-----------------------------------------
//where
emps.Where.LastName.Value = "%A%";
emps.Where.LastName.Operator = WhereParameter.Operand.Like;
emps.Where.HireDate.Conjuction = WhereParameter.Conj.Or;
emps.Where.HireDate.BetweenBeginValue = "2001-01-01 00:00:00.0";
emps.Where.HireDate.BetweenEndValue = "2001-12-31 23:59:59.9";
emps.Where.HireDate.Operator = WhereParameter.Operand.Between;
emps.Query.Load();
//获取特定的列
emps.Query.AddResultColumn(Employees.ColumnNames.EmployeeID);
emps.Query.AddResultColumn(Employees.ColumnNames.LastName);
emps.Query.Load();
//Order By
emps.Query.AddOrderBy(Employees.ColumnNames.HireDate,
WhereParameter.Dir.DESC);
//使用 Distinct
emps.Query.Distinct = true;
//Select Top N
emps.Query.Top = 10;
-----------------------------------------
小结:dodads只支持对单个表、视图、存储过程进行操作,不支持多表查询,不支持表关系,如果要做这些工作,建议创建视图或存储过程实现,您也可以直接使用doodads的接口调用手写的sql
下一节将介绍doodads对事物和存储过程的支持。
2009年5月27日
摘要: 关于.net下的ORM框架,大家最为耳熟的可能就是NHibernate了,当然,很多公司正在使用自己开发的ORM框架,笔者至少见过3家不同公司的ORM框架,其实都是大同小异,借助于codesmith、mygeneration等代码生成工具,自己开发一个ORM框架也不是什么难事,关键的问题是,你能不能设计出代码优美简洁、功能灵活、定制方便以及部署容易的ORM框架。 我去年开始热衷NHibernat...
阅读全文
2009年5月17日
摘要: 相信不少程序员喜欢使用Emeditor,我也经常推荐朋友使用这个工具,有时候就会有朋友问我,“这个工具有什么好啊,我现在还体会不到它的好处”,现在我就把平时积累的一些emeditor经验拿出来与大家分享,如果读者有一些其他的觉得适用的,可以留言或者联系我加入到本文。一、快速测试html、javascript(关键字:web预览插件,html模板)有时候我们想快速预览一段从其...
阅读全文
2009年2月20日
摘要: 这篇文章献给在10分钟之内不能写出最简单的联动下拉列表以及想了解写法的人相信80%的web程序员都使用过联动菜单,这其中又有至少50%的人使用过或只使用过省份、城市联动下拉列表,但是,这其中会有一部分人只是拿来主意,并不会自己写,而且望着网上繁杂庞大、各式各样的联动下拉代码产生了学习恐惧感,今天我用简化问题的策略来告诉大家,这样的代码其实很简单。所有的联动菜单归根到底都是对select元素的操作,...
阅读全文
2009年2月6日
摘要: 先给出一个需求:数据表中有一列存储了一些脏字,比如:a*bc*de\*f...现在想把该字段所有的"*"号替换成"\*",但是如果*号前面已经有了\,则不必替换如果你可以用正则表达式很快解决这个问题,可以不必看下面的文字 -------------------当然解决这个问题有很多方法,现在我们尝试用正则表达式去解决,查阅了很多资料,尤其是这篇文章:《正则表达式30分钟入门教程》版本:v2.3 (...
阅读全文
2008年12月24日
摘要: 本次重大修订: 代码自动完成 菜单栏快捷键,F5预览代码 其他小bug下载地址:/Files/xiehuiqi220/vcssGreen13.rar
阅读全文