BASE64 VLQ 编码规则

首先我们先来了解下 VLQ 是什么,VLQ 是 Variable-length quantity 的缩写,是一种通用的,使用任意位数的二进制来表示一个任意大的数字的一种编码方式。这个编码方式是在 MIDI 文件格式中定义的,用来节省空间。在其他地方也有很多类似这样的编码格式,比如在 Google’s protocol buffers 中,还有我们马上要讨论到的 BASE64 VLQ 中。想了解的更多,请参考wikipedia

我们先来看看 MIDI 中的 VLQ 编码是如何编码 137 这个数字的吧:(摘抄自 wikipedia)

  • 先把 137 转换成二进制:10001001
  • 7 bit 一组,把二进制分开,不足的补 0 ,变成 0000001 0001001
  • 把最低的7位拿出来,在最高位补0表示最后一位,变成 0000 1001,这个作为最低位,放在最后边。
  • 在其他组的最高位补 1 ,表示没有结束,后面跟着还有数据。在这里就是 1000 0001
  • 拼在一起,就变成了 1000 0001 0000 1001 .

这就是 VLQ 的变化过程。

那么什么是 Base64 VLQ 呢?和上面的变换过程有什么区别呢?

我们可以先来参考我博客的另外一篇文章,先来回顾下 Base64 编码:BASE64 编码规则

我们可以看到 Base64 是一种可以把二进制数据编码成用 ASCII 表示的一种编码规则,但是受限于 Base64 采用的字符集,一个 Base64 字符只能表示 6bit 的数据。所以上面的 VLQ 中 7 bit 一组的分组方式,在这里就要变成 5 bit 一组的分组了。

另外,Base64 VLQ 需要能够表示负数,于是规定了需要先把数字变成无符号数,用最后一位来作为符号标志位。我们直接来做一个变换吧,这样理解的最快。在例子中可以看到和上面的 VLQ 编码还是有一定差别的。

不妨还拿 137 来做示例吧。

  • 先把 137 转换成二进制:10001001
  • 由于 137 是正数,所以在最低位补0 变成 100010010
  • 按照 5bit 一组的方式分组,变成 01000 10010
  • 按照从低位到高位的顺序,以 5bit 一组为单位,依次拿出数据做转换。
  • 先拿出第一组 10010 , 因为后面还有数据,所以需要在高位补 1,变成 110010 ,编码成 Base64: y
  • 再拿出第二组,也是我们这里的最后一组,01000 , 由于是最后一组,所以在高位补 0 变成 001000,编码成 Base64: I
  • 按照从低位到高位的顺序把这些 ASCII 字符拼接起来,变成 yI

可以看到在 VLQ 中,编码顺序是从高位到低位,在 Base64 VLQ 中,编码顺序是从低位到高位。

那么如何解码呢?相信了解了编码过程后,解码过程就不必再讲解了。平时也基本不会去手工去算这些东西。这里推荐一个在线编码解码的网站:http://murzwin.com/base64vlq.html , 同时如果你想在代码中使用,Mozilla 的一个开源库里有相关实现:https://github.com/mozilla/source-map/blob/master/lib/source-map/base64-vlq.js,这个是 javascript 的实现,其他语言的实现,如果你需要,请自己找找,或者根据编码规则自己写一个。

说了这么多,好像还没讲 Base64 VLQ 运用在什么地方,这次我不打算说了,准备下一篇博客再来解释这个问题。

textarea 中的计数在前端和后端之间的差别

计算 textarea 中用户输入字符的个数,给出用户提示,并在前端和后端同时校验长度是非常常见的需求。但是在前端和后端,对于带有换行的文本的长度计算却有一点出入。

简单的说来,在前端和后端如果都直接计算字符的长度,那么,一个换行,在前端,长度计算是1,而在后端计算出来是2。

我写了个简单的 DEMO ,你可以点开看看,注意查看源代码。截图如下:

我们可以看到第三个字符对应的 unicode 编码,然后我们到 http://www.unicode.org/charts/PDF/U0000.pdf 这里来查看编码对应的字符,可以看到 61 对应的是字符”a”, a 对应 “NL(new line)”,62 对应的是字符“b” ,也就是说在 a 和 b 之间只有一个“NL”,所以,我们计算的长度为 5。

接着,我们提交表单试试,打开调试工具,选择录制请求,可以看到如下的结果:

可以看到,提交表单的时候,换行符就变成了 %0D%0A , 我们可以查到这两个字符对应的是 “CR(carriage return)” 和 “NL(new line)” ,所有后端在计算这个长度的时候,就变成 6 了。

那知道这个问题的存在了,解决办法就有好几种了,你可以在前端计算 length 的时候,把 \n 替换成 \r\n 再计算,和后端保持一致,也可以在后端做替换和前端保持一致。也可以在前后端都忽略掉换行符。具体的方法取决于你的业务场景。

感谢 xj.ye 的评论,在不同浏览器下表现也是不一致的,主要是 IE 和其他浏览器的区别。

尽快抛弃 photonVPS 这家烂 VPS

用了 photonVPS 这家 VPS 两年了,以前还觉得还将就用用,毕竟相对比较便宜嘛。但是自从今年过完年,续费了半年后,一切都变的非常糟糕,现在终于忍无可忍,迁移到了 Linode , 下面我来讲讲这家 VPS 到底有多烂。

我专门去后台看了下,从今年2月份,到现在,4个月左右的时间,我总共发了 12 个 tickets:

最常遇到的问题是,不能 ping localhost 、网络访问不了。从截图中可以看到,这些问题是经常发生。这些还不包括我没注意到的。毕竟我就是放个博客而已,很多时候也没注意到博客打不开。遇到这些网络问题后,客服想到的并不是去检查哪儿配置错了,而是经常询问我,我可不可以帮你重装系统啊,你要备份好数据哦。备份你妹啊,重装你妹啊。重装对于你们来说当然简单啦,全自动化的操作吧。系统装完我要配置软件环境吧,我哪儿有那么多的时间陪你们玩啊。

到后来,我每次发 ticket 都要事先说明,千万不要询问我是否可以重装系统,答案是不可以。这样也只能保证客服的第一条回复不提重装的事情,但是事情如果解决不了,第二条回复立马就问我可以重装系统吗?,艹,和这种人交流真是急死个人啊。他们的客服貌似不会关注你这条 ticket 的其他内容,只会关注你的最后一条,这个很让人着急啊,你经常需要重复的讲同一个问题,帮客服了解完整的处理过程。

另外他们号称提供中文客服,有一次,我还真写了中文的 ticket 试试,他们竟然回复英文,那是他们用机器把中文翻译成英文,然后让客服回答的吧。这种提供中文客服的方式也太坑爹了吧。

今年出的最严重的一个问题是,他们的物理硬盘挂掉了。造成写文件全部是 disk error, 到最后整个机器全部崩溃了,启动不起来了。由于写文件全部 disk error ,在最开始可以登陆,网络通的情况下,我想备份数据也备份不了了,因为无法打包。为了这个问题,交流了几天,最后他们才承认是物理硬盘坏了,VPS 系统文件已经损坏了。然后让我通过母鸡进去打包我要备份的数据,到指定目录,然后他们帮我备份数据,最后 rebuild 系统。我登陆进去,打包了一小部分数据,又 disk error 。真让人崩溃啊。还好的是,最后来了一个牛 B 的工程师,直接把 VPS 给恢复了,才得以没有灾难性的丢失数据。这个问题足足花了一天多才解决。首页还写着 uptime 99.9% 呢。这太扯淡了,我提到了他们说的 uptime 99.9% ,他们什么都没有表示。

以后不管在哪儿,只要遇到有人让推荐 VPS , 我就要去说,千万不要选 photonVPS , 然后贴这个博客的链接给他们看我的遭遇。

遇到有人问 photonVPS 好不好?photonVPS 怎么样?我都会去回复下,千万不要选这个,然后给出这个链接。

前天提的 ticket 说不能 ping localhost,这个会造成 wordpress 的后台自动更新功能不能用,因为它要连接本地的 FTP ,这个今天终于给我解决了,当然中间又少不了那句经典的:shall we rebuild your vps? Do you have any important data on vps? 我最后回复了:谢谢,但是我不再需要了,因为我已经迁移到 linode 了,再也忍受不了你们的垃圾服务了,你们动不动就问用户是否可以重装系统,太垃圾了。我会写blog告诉大家我的经历,让大家千万不要买你们的服务。再见。

============== 2013-7-3 update ==================

这个事情过去一年多了,到现在还有不少人能搜索到这里来,然后在下面留言。有些是已经上了贼船的,有些是上贼船之前看到这个博客的。不管怎么样,能够告诉大家我的遭遇,让更多的人避免受骗,我就觉得这个博客写的太值了。

现在不只是我自己的遭遇了,还有下面这么多网友的回复,都是 PhotonVPS 是个垃圾 VPS 服务商的最佳证据。

另外,我从写这篇博客开始,迁移到了 Linode,在这一年的时间里,只出现过一次访问不了的情况,最终通过发 ticket 换 ip 解决,大家应该明白这个不能访问是怎么造成的吧,不怪 Linode … Linode 响应 ticket 非常快速,而且很专业。这一年以来,维护 VPS 的工作量大减,省了不少心。前段时间 Linode 还搞了免费的硬件升级,买的时候内存 512M ,现在都免费到 1G 了,真是业界良心。

如果你觉得这个文章对你有帮助,并且你也准备买 Linode,不妨点这个链接去购买:http://www.linode.com/?r=434bcb5fd06364a329c09a0db255e22e09def513 。通过这个链接购买的用户,对你没有任何损失,但当你使用 Linode 90 天后,我可以获得 $20 刀用来后续购买 Linode 的服务。先谢谢各位了。

2011个人总结

在开始写这篇博客的时候,还有20分钟就要到2012了。我觉得我还是需要来总结一下的,仔细回顾一下这一年我做了什么,什么做好了,什么没做好。

首先,打开了一年前这个时间写下的日志, 先看了下希望能做到的事情。第一条,购入一台Mac,这个完成了,在3月份买入的,这个投资现在看来是值得的。第二条,做了,但是做的不够好,开始有意识的节流,但是积蓄还是很少,这个来年继续做吧。第三条,尝试读了心理学的,还尝试读了小说,第一次读完一个长篇小说《1Q84》。第四条,几乎没做,不过在这个夏天,还是通过游泳、瑜伽、普拉提成功减肥10斤左右。第五条,这一年我总共写了8篇博客,太少了。第六条,我还是单身。

这一年,我做了什么呢?现在想起来,好像还真是充满坎坷呢。是本命年的缘故吗?不,我从来不信这个,连红内裤都没穿。这也许就是成长路上必须经历的吧。先是信心满满的开始做一个大项目,和团队合作的很愉快,但是在项目一期快完成的时候,项目却被停了,所有的努力都白费了,和失去了自己心爱的东西是一样的感觉。不过不管怎么样,也是有收获的,比如在技术上的积累,以及认识了一些朋友。

这个半途而废的项目结束之后,就开始做了很长一段时间小需求,还遇到了几个非常不靠谱的人,然后发了几次脾气,被投诉了几次。那段时间还被老大拉去谈话,说我这个要改。哎,我也不想为了这些事情去和别人吵架,但是每次遇到这些不靠谱的人的时候,我就很难忍住,总觉得和他们合作太浪费我的生命了。

不过还好,这样的日子不算太长,接下来由于架构调整,就去做我的阿里这个产品线了。下半年的大部分日子都在做这个,状态不错,主要是这个产品线的其他同事都比较靠谱,和靠谱的人合作,心情和效率都会很不错。接下来还要继续在这个产品线,我也有一些关于这个产品线的前端方面的规划,手头项目忙完,会好好整理一下。

下半年,还有一个项目对我的锻炼也蛮大,是 web IM 项目,这个项目前期,我就想了很多,然后我想根据需求想了一整套设计方案,来适应当前的应用场景和未来的应用场景,然后去给项目组其他成员讲这些,得到了一致认同。不过悲剧的是,项目中途遇到了一些技术难题(主要不是我负责的这块),然后当时很难搞定,就暂停了,这个我也有一部分这人,在项目前期,没有认真考察这些技术的可靠性,就想当然的开始编码了。还好现在这些已经有了进展,不过是其他同事在跟进,我实在是抽不出时间了。

好了,工作上的事情就到此为止,再回顾下生活上有什么进展吧。

首先,到现在我还是单身,好像也从来没怎么去努力摆脱这个现状,这个要批评自己了,2012要好好努力,哪怕世界毁灭,也希望能有一个心爱的人和我一起欣赏最后的风景。

一个人在外,每次有朋友来杭州都特别高兴,今年在杭州还是见了不少朋友,也是你们,让我在杭州的生活增添了不少色彩。

今年去了上海,去了南京,去找老朋友们玩,每次都玩的很开心,和这些老朋友们相聚,总是会回忆起学校的美好时光。遗憾的是,一直说的要去苏州的,甚至有次酒店都定好了,结果由于一些原因没有去,就再也没去过了,现在苗苗都走了,更不会去了。

另外今年还和同事们一起去了徽杭古道,一起去了舟山溗泗,一起去了西塘,每次都玩的很开心,感谢有这么一群可爱的同事们。去徽杭古道让我体验了一下睡帐篷的感觉。去溗泗我第一次下海水游泳,第一次尝到了海水的味道。西塘是我去的第一个江南古镇,虽然我觉得最好玩的是晚上大家在酒店玩狼人。

2012, 我要见更多的老朋友,去更多的地方看看,也要带爸妈来杭州看看。

2012,我要继续减肥,为了自己的健康,希望不再有脂肪肝。

2012,我要阅读更多种类的书籍,来完善自己。

2012,我要学会更合理的消费,开源节流。

2012,我要继续写博客,继续分享我认为值得分享的东西。

2012,我要在技术上精益求精,大胆尝试新技术,让新技术能和产品完美结合起来。

2012,我要学会控制自己的情绪,但是对待事情要同样的认真。

2012,我不要再一直一个人过。

Mac 在无法启动的情况下备份数据

上周,我的 MBP 悲剧的突然出现了无法启动的情况,启动的时候,出现一个进度条,然后这个进度条走不完,就会被关机。阅读说明书上的方法,先进从 recovery 盘启动,用磁盘工具检查硬盘,可以发现磁盘错误,但是尝试紧急恢复总是失败,然后又尝试用系统盘进入磁盘工具检查硬盘,结果一样,可以看到错误,但是无法修复。这个时候,我决定格式化硬盘重装系统了,但是数据还没备份出来呢,这个时候也没办法进入系统,没办法挂载这块有问题的硬盘。后来经过其他人的提示,想到了 single-user mode ,试了下,还真成功备份出数据来了。不过有一些技巧,下面记录下在 single-user mode 环境下,如果挂载移动硬盘用来转移数据。

1,连接好移动硬盘,然后启动 Mac 到 single-user mode (启动的时候按住 command + s ),记住,一定要在启动前连接好移动硬盘,中途插上,我试了好几次都没成功。

2,按照提示,输入
/sbin/mount -uw /

/sbin/fsck -fy
两个命令用来用读写模式挂载硬盘和检查磁盘。这个时候,如果你的情况和我一样,这个时候 /sbin/fsck -fy 应该会报出错误,但是没关系,接着往下操作。

3,执行
ls /Volumes
这个命令将显示所有被挂载的磁盘,你的移动硬盘或者U盘很可能还没在这里显示,那就说明还没有被挂载。没关系,如果没被挂载,我们先在这里创建一个挂载点。例如:
mkdir /Volumes/usb

4,我们需要确定挂载的移动存储设备的磁盘编号:
ls /dev/disk*
一般情况下,移动存储设备的编号在最后面,例如 /dev/disk1s1

5,现在,挂载移动存储设备到刚才创建的挂载点,执行如下命令:
/sbin/mount_msdos /dev/disk1s1 /Volumes/usb
由于我的硬盘格式是 FAT,如果你使用的硬盘或者U盘格式不是这个,可以在 /sbin/ 这个目录里找到对应的 mount 工具,执行命令。

6,如果挂载成功,你现在可以通过运行:
ls /Volumes/usb
查看移动存储设备内的文件了。

7,可以尝试从机器内的硬盘复制文件到移动存储设备了:
cp /Users/your_user_name/Documents/somefile /Volumes/usb/
如果成功,那么就可以把你的重要数据备份出来了。

这个方式是参考自:http://www.macsage.com/mounting-usb-drive-in-single-user-mode/

另外,如果你有办法在 single-user mode 下搞定网络问题,那么也可以通过 SSH,FTP等方法来备份,single-user mode 下面还是有蛮多的 UNIX 标准工具。

如果你的 Mac 硬盘遇到和我一样的问题,希望这个文章能帮到你。

localStorage in HTML5(2)

上一篇博客简单的介绍了下 localStorage,并且对各个浏览器的存储空间大小做了简单的测试。在上篇博客到这篇博客期间,世界也发生了很多变化,IE9 和 firefox4 正式版都发布了。于是我也对这两个新的浏览器进行了测试,关于 localStorage 的, IE9 和 IE8 表现一致,FF4 和 FF3.6 表现一致,和上篇博客中介绍的一样,FF4 在 Mac 下和 WIN 下表现仍然不一致,参考上篇博客。同时,给出我写的测试存储空间大小的页面,你可以自己来试试:http://lab.allenm.me/html5/storage/maxtest.html

除了最基本的和使用 cookie 一样使用 localStorage,我们还能用它来做什么呢?

如果你看过 localStorage 的文档,你应该注意到了我们在改变 localStorage 中存储的数据的时候,会触发一个 storage 事件:

interface StorageEvent : Event {
  readonly attribute DOMString key;
  readonly attribute any oldValue;
  readonly attribute any newValue;
  readonly attribute DOMString url;
  readonly attribute Storage storageArea;
  void initStorageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg, in any oldValueArg, in any newValueArg, in DOMString urlArg, in Storage storageAreaArg);
};

 

既然我们可以知道此“源”下的localStorage 中的某个字段的值发生了变化,那我们就可以在前端做到跨页面通信,这个是有意义的。 你想想看,在我们目前的WEB应用中,经常会发生这样的事情:在淘宝或者其他电商网站购物,点击购买某个物品,会在页面上购物车中显示。然后在新的 tab 页中打开其他物品的页面,也点击购买,新的页面当然会显示你购买的所有物品,但是旧的页面中的购物车却并不会主动更新这个数据。以前的技术并不是不可以实现这个,只是相对来说成本较大,没有必要。利用 localStorage ,我们就可以只使用前端技术来同步这个数据,成本极小。

我写了一个简单的利用 storage 事件来做前端层面的夸页面数据同步,请在支持 localStorage 的浏览器中打开两个此页面:http://lab.allenm.me/html5/storage/ ,然后在任意一个中输入任意字符,再看看另外一个页面中有什么变化。

我们知道 localStorage 中,我们只可以保存字符串。但是有些时候,我们需要保存一些结构比较复杂的数据,字符串不适合做这种工作,自己再制定一种特殊的规则来利用字符串保存这些数据,也是不明智的选择。因为我们已经有了 JSON 这个事实上的标准了啊。要让 localStorage 支持 JSON 的存储也比较容易,我们只需要自己再封装一层就OK了。现代浏览器已经原生支持 JSON 的解析,JSON.parse() 用来把字符串解析成 JSON 对象,JSON.stringify() 用来把 JSON 对象编码成字符串格式。有了这两个方法,我们只需要在存储的时候,编码,获取数据的时候,解码就可以实现用 JSON 来存储数据了。具体封装这里就不给出代码了。

即使有些不够现代的浏览器不支持 JSON.parse() 和 JSON.stringify() 也没关系,因为我们还有开源的 js 实现的 JSON 的解析器和编码器:老道的 JSON-js

localStorage 还有一个孪生兄弟,叫 sessionStorage,他们的用法基本一致,同属于 WEB Storage, 只是保存的数据的生命周期有区别,详情请阅读这里

阿里巴巴中国站大力招聘前端工程师以及视觉、交互

欢迎各位自荐或者推荐,简历请发送到 i [at] allenm.me, 下面是各职位的 JD

地点:杭州

前端开发工程师:

We build the web,
making the world and ideas in our dream come true.

职位描述:
1、根据产品原型开发前端代码, 并配合我们的后端工程师完成后端数据的接口;
2、解决主流浏览器及其不同版本之间的兼容性问题;
3、优化网站的前端性能, 保证网站的高质高速;
职位要求:
1、熟悉掌握各种Web前端技术基础: (x)HTML、CSS、JavaScript、ActionScript等, 有JavaScript|| ActionScript高级应用经验的尤佳;
2、理解Web标准,对可用性、可访问性等相关知识有实际的了解和实践经验;
3、了解一门后端语言(如Java、PHP、C++、Python、Ruby), 并能将其和前端语言进行配合;
4、个性乐观开朗, 思维逻辑性强, 善于和各种背景的人合作;
5、专业不限,其中计算机、数学、自动化等相关专业优先考虑;
6、富有创业精神, 充满激情, 乐于接受挑战.

在以上要求基础上,有以下任意一点将优先考虑:
1、参加过开源项目
2、喜欢混迹各大技术社区,并有自己的声音
3、互联网重度使用者
4、了解相关前沿技术
如果你有 twitter, facebook, 个人blog 等一些社会化的东东,麻烦告知我们,另外可以告诉我们为什么要成为一名前端攻城师
如果你想更多的了解我们,可以登陆我们UED的博客:www.aliued.cn

交互设计师:

职位描述:

  • 参与网站产品前期的规划构思,完善产品概念。
  • 根据产品需求制定交互方案,输出产品原型和设计说明文档。
  • 对产品进行持续的设计优化,提升用户体验。

职位要求:

  • Nice,open,有同理心,擅于换位思考,对新鲜事物充满好奇,擅于发现。
  • 对交互和用户体验设计有深刻理解,具备自己完整的知识和理论体系,掌握基本的UED设计方法。
  • 2年以上互联网体验设计经验,熟悉网站设计流程,至少独立完成过一个大型完整项目中的交互设计工作。
  • 具备较强的逻辑思维能力和表达沟通能力。擅于说服和达成共识。
  • 丰富的知识和阅历,对用户习惯有研究,具备一定的设计前瞻性。一定的视觉设计和html技能。
  • 工业设计、计算机、视觉传达、心理学、信息学相关背景;资深网虫。

视觉设计师:

职位描述:

  • 负责网站产品界面的视觉设计及产品的在线推广设计工作。
  • 负责产品的情感需求分析,创建原型。和产品开发团队共同创建界面工作。
  • 实现界面的视觉和美术设计方面的设计,如图标、主题、背景等。制定产品用户界面的风格及标准。
  • 参与产品在线推广活动的策划与设计实现工作。
  • 吸引用户使用产品。

职位要求:

  • 本科以上学历,美术,视觉传达,工业设计相关专业,2年互联网工作经验。
  • 对用户界面设计,交互设计相关工作有浓厚兴趣,富于团队精神。
  • 熟悉界面设计的流程方法,出色的设计语言表达能力,优秀的创新与沟通协调能力。
  • 精通photoshop、illustrator、flash、dreamweaver等常用制作工具;懂htm语言。
  • 熟悉3D或actionscript语言优先。
  • 对互联网产品有强烈兴趣并具有一定的商业灵敏度。富有创造力和激情。


IE文本域中回车自动提交表单

当表单中只有一个文本域的时候,在文本域输入完后按回车,IE会自动帮你提交,(谢谢Andre提醒,其实这种情况在其他浏览器里也会提交的,我测试了firefox,opera, chrome。safari没测试,不过表现应该和chrome是一样的,所以主流浏览器都会自动提交,而不仅仅是IE)哪怕没定义 submit按钮,也会提交。

这个是今天在解决一个其他BUG的时候,了解到的这个问题,虽然要解决的BUG和这个没关系,这个一会儿再说。

先说这个怎么解决吧,在form里建个隐藏的input标签就可以了,可以这样  <input style:”display:none”/> 。

另外我要说说,大家要慎用IE tester这个东西啊,太不靠谱了,在这个里面执行JS和原生浏览器执行,有很大差别。今天想用这个来解决IE6的一个BUG,一直没进行到要真正解决的部分去,因为我一直以为是上面的那个问题带来的BUG,只到我用机器上的IE8运行了一段测试代码,又用IE tester新建IE8来运行,结果不一样,当时就囧了,我意识到做了一个晚上的无用功了。

只好马上用Virtual BOX安装 XP了,用原生的IE6来解决问题,果然,问题不在那里,很快解决了BUG。

所以建议大家一定要慎用IE tester,尽量用原生的浏览器来测试。

然后今天遇到的实际的BUG,是因为在js中对字符串处理的时候使用的非标准的方法。我想返回字符串中指定位置的字符,我使用了类似PHP的方法:

var a=’hello world’;

var b=a[0];

这样在firefox中是有用的,b是 ‘h’ ,但是在IE下是不起作用的,翻了手册才知道,标准的方法是 charAt().

var b=a.charAt(0);

要这样才是标准的方式,换了这个后,马上就解决了要解决的BUG。

开始寻找实习机会了

着手准备简历了,发现大学过的真失败啊,简历上没有什么可写的,真悲哀啊。

没得过奖,没在学生会,社团混过。

英语六级还没过,虽然四级成绩还马马虎虎。

没有做过大点的实际项目。

总之基本一无所有了。

努力吧,好好利用最后这点时间吧。