我的本命年

本命年常犯太岁,无喜恐有忧。

无论喜忧几多,本命年(生肖年以二十四节气作为时间参考)已经接近尾声了,最忧的还是时间流逝得太匆忙。采薇采薇,薇亦作止。曰归曰归,岁亦莫止。第一次没有在家乡过年,感觉也不错。杭州飘着小雪花,鞭炮声零零落落,街道上行人隐约,车流稀疏,虽然少了些许年味,似乎也会让人跟@jeffery一样忍不住大爱这个城市了。

看到了很多人的年终总结,读那些不一样的奋斗史,不一样的人生轨迹也别有风味。年末的时候太过忙碌,很久没有写点东西了,一年到头,也总要总结一下,算是回顾一下过去,点评一下现在,展望一下未来。

回想2011,已经有太多的事情记不清了。整个一年里,基本上都是浑浑噩噩,栖栖遑遑地过来的。上半年还挤得出一些时间,基本上都给了3个女孩。安妮是其中之一,《绿山墙的安妮》的主人翁,乐观主义者,欢乐制造者,还是一位喋喋不休又可以很安静的姑凉,她说话时,让人百听不厌;要是静了下来,就可以安然入睡了。苏菲是第二位,《苏菲的世界》虽然没有为这个女孩设计很鲜明的个性,但是跟随她一起做一次时空穿越也是蛮刺激的。第三位是《蘑菇的理想国》里的主角蘑菇小姐,你要是想读这本书,我相信你肯定找不到它的ISBN号的,因为根本就没有这本书的存在,蘑菇是确有其人,外表沉静冷漠,内心情感丰富,一个典型的INFP。跟这样的人在一起,可以很舒心,很随性,有些事情是可以预见的到的(我发现自己有预言家的潜质),以后可能不会再相见了吧。本想留点东西做个纪念,后来也没能成功,或者这样更好。

年中,公司的变动,团队的变动,业务的变动很剧烈。很多人都很不舍,但是离开未必不是一件好事。饺子哥的名言很有哲理:去哪里不重要,重要的是离开。我在创业公司、小公司、大公司都呆过,所以认同格雷厄姆一个观点:运营创业公司,每天都像在战斗;而为大公司工作,就像在窒息中挣扎。祝福美食行。

在公开场合,听多了“这路上”、“在一起闯天下”、“路走对了,就不怕远”这种冠冕堂皇的话,但是私底下不能太当真。公司创业犹如行军打战,上下同欲者胜。喊口号显然不是打胜站的关键因素,赞歌也唱过了,但是制定了错误策略的那些人却没有出来向付出了辛勤劳动的人致歉。

一次次的失败或多或少会给人打击。《鼠胆龙威》中的第一反派说的真的是挺对的:人一定要靠自己。身为男儿,就要对自己狠一点,立业是人生当中非常重要的一件事。

十月份又搬回了滨江,那个08年毕业就来到的地方,租了个大房子,和老哥住在一起。机缘巧合,那些在创业公司一起呆过的朋友也都回到了滨江。于是还是可以经常聚在一起。

最后的两个月里,基本上都献给了工作。很多天都是忙到后半夜,很多个周末也拿出来了,老哥说要去湖州吃羊肉,我说没时间,朋友要出来活动,我也说没时间。除了项目上的事情,闲暇时间也用来去成都、广州、深圳、北京支持市场部做推广。

俄罗斯的蔡格尼克有个心理效应(中文资料不是说他是英国人,就是说他是德国人、法国人,我想wikipedia英文站应该是对的吧):人们之所以会忘记已完成的工作,是因为欲完成的动机已经满足;如果工作尚未完成,这同一动机便使他对此留下深刻印象。如果一个复杂的事情一直在持续,积累在心里,那种精神压力是不可小觑的,因为晚上做梦也经常会想到它们。那些半夜三更在公司的时候,我会思考这样的问题:忙成这样的人不猝死,天理难容啊。当然,老天爷本来就是不讲理的。

忙一点不可怕,可怕的是有一些非常闲的朋友。记得有个周五,想着周末可以放松一下的时候,朋友来电要一起出去玩,于是就去玩了一整晚上游戏。早上回来的时候,感觉全身轻松,那些时候,玩上一晚上游戏真的就等于是好好地休息了一场。

《黑客与画家》给了我不少启发,一切事物是可以解释的,我们在这个环境下生存,或许过的并不好,但是最拉风的解决方式还是去勇敢面对,而不是选择逃避。在学校里大家都一样,同一个教室坐着,上着同一堂课。到社会上之后,大家的价值观都会受到来自四面八方的冲击,有的人成为教师、工程师、设计师、公务员…。有的人结婚了,表面上还是很顽皮;有的人生子了,也就生子了。每个人的意识形态都在重组,或者以前的朋友不再那么亲密了,或者未来的梦想已经没有了,宿命论者也没办法保证一个人永远不变。虽然这是一个让人悲痛的时代,它摧残了无数人生存下去的勇气,但是机遇也是无处不在的,养活自己可能并不困难,如何生活是更应该要考虑的。

叔本华说:人类幸福的两大敌人是痛苦和无聊。人生就是痛苦和无聊之间的钟摆。大家都在赶时间,赶时间上班,赶时间做饭,赶时间应酬,到底赶的是谁的时间呢?我想停下来,再听安妮说一次:脚下的路是窄的,恬静的生活中幸福之花会一路绽放。

每个人都有安慰自己的方式,正如《侏罗纪公园》里所说的一样:生命总会找到它自己的出路。

新的一年大家应该都有不同的计划,不同的期盼吧。不管怎么样,大家都是在努力地活的更好。希望大家在马斯洛金字塔上步步高升。

上帝在天,愿世间太平无事。

Posted in 默认分类. 没有评论 »

再谈JavaScript继承

以前写过一篇blog叫也谈JavaScript继承,现在回过头来看,发现还是有待争论和改进的地方。我们的目的是让两个类之间建立继承关系,大家应该知道,JavaScript中的继承关系需要用原型链prototype来实现,那么到底应该如何做才算比较好呢?

var inherits = function(sub, parent){
    //如何继承呢?
}

首先,ECMAScript 5增加了许多API,如果浏览器得到了支持,我们应该很好的利用起来。Object.create, Object.defineProperties都是比较好玩的API,看看如何使用这些新的API来实现继承:

var inherits = function(sub, parent){
    sub.prototype = Object.create(parent.prototype, {
        constructor: { value: sub, enumerable: false }
    });
}

上面这段程序把父类prototype上的东西复制到子类,并把子类的constructor指向子类的构造函数。同时设置constructor的enumerable属性为false,这样for in循环是就遍历不到constructor属性了。

其次,假如JavaScript对ECMAScript的具体实现中使用到了__proto__这个属性,那么借助它是最容易达到继承的目的的:

var inherits = function(sub, parent){
    sub.prototype.__proto__ = parent.prototype;
}

如果上述条件都没有,我们通过借助一个辅助函数来实现原型链的绑定了:

var inherits = function(sub, parent){
    var clone = function(o){
        var F = function(){};
        F.prototype = o.prototype;
        return new F();
    }
    sub.prototype = clone(parent);
    sub.prototype.constructor = sub;
}

为什么需要new出一个辅助的Function,而不是直接使用如下常见的实现方式:

sub.prototype = new parent();

一般来说,将子类的prototype赋值为父类的实例不会有问题,但是parent函数无辜地被执行了一遍,某种特殊情况下真的会出现一些问题,比如parent的构造函数做了一个事情——记录parent的实例个数,那么这个时候的记录结果应该是有误的。而借助辅助函数的做法则可以避免这个问题。

综合各种实现方式组合成最后的解决方案:

var inherits = function(sub, parent){
    if(Object.create){
        sub.prototype = Object.create(parent.prototype, {
            constructor: { value: sub, enumerable: false }
        });
    }else if(sub.prototype.__proto__){
        sub.prototype.__proto__ = parent.prototype;
    }else{
        var clone = function(o){
            var F = function(){};
            F.prototype = o.prototype;
            return new F();
        }
        sub.prototype = clone(parent);
        sub.prototype.constructor = sub;
    }
}

最后要提醒一句的是,不要试图用这种方式继承Array。有兴趣研究Array继承的朋友可以转驾到这里:How ECMAScript 5 still does not allow to subclass an array.

To Be A Better Man

每个人都会在那么一些时候去思考人生,思考人生的意义,寻找人生的目标。而这些时候往往是他们缺乏人生的意义和目标的时候。思考久了,或许就会提出类似to be or not to be的问题。今天周会上@合沙就抛出了这个话题,结局大概也能猜到,就是人生本来就TMD没有意义,需要人为地给它安置一个意义,加之每个人的价值观不完全一样,所以每个人心中的意义也不一样。愚蠢的人类啊。~

在吕克·贝松执导的地下铁(subway)里,影片开始给出了3句话:

  1. to be is to do – 苏格拉底
  2. to do is to be – 萨特
  3. do be do be do – 辛纳屈

这里要感慨一下:这三句话真TNND的晦涩难懂啊。

剧中的结局或许是悲剧,但却是圆满的。男主角虽然付出了生命,但是也实现了自己的梦想,也算是诠释了to be的意义吧。

回家路上,@正乐乐乐说认识世界应该从朴素唯物主义的角度去认识。事物是客观存在的,感官的认识不可靠。@合沙则持相反意见,他觉得个人认识的世界存在于内心之中,感知即世界。我想@正乐乐乐偏向一个理性主义者,而@合沙则偏向一个经验主义者。由于我和@合沙站在一个立场,@正乐乐乐最后差点转变自己的观念,可怜的乐哥。

十七世纪的理性主义者的代表有法国的笛卡尔,荷兰的斯宾诺莎,德国的莱布尼茨。而到了十八世纪,英国的经验主义开始盛行,洛克、柏克莱和休姆都是英国人,他们对理性主义者进行了批判。到了十八世纪中叶,哲学中心从英国移到法国,孟德斯鸠、卢梭和伏尔斯泰到到过英国,他们既受到受到了洛克(洛克最早强调立法权于行政权必须分立,孟德斯鸠则提出了政权分立的思想)政治思想的影响,又受到牛顿自然科学的启发,对传统的权威越来越不满,于是发生了后来的法国大革命。到了十八世纪晚期,哲学中心移到了德国,大哲学家康德出来吼了一嗓子:我们对这个世界的认识是同时透过感官和理性而得到的。

这事就算完了。

当然仁智见仁,智者见智。没过多久,康德就成过去时了,浪漫主义哲学家谢林、黑格尔开始引领时尚潮流。

http://www.xiami.com/song/1333147





Posted in 其它. Tags: . 没有评论 »

发布jsxml

本年度D2前端技术论坛有幸上台show了一把,分享了一下前端TDD的一些心得,感受到了国内前端发展的盛况。第一次做大型分享,也能认识到自己很多不足之处,应该有人听得睡着了吧。

为了这次D2,2周之前我开始了jsxml这个项目,我遵循TDD的原则来开发,发现整个过程都很有意思,我可以大胆地重构,也可以随时开始编写代码,也可以随时停下来。最后完成的时候发现比预计的时间还要少,也许这就是想和做的差别吧。

jsxml可以对XML进行查询和编辑,在nodejs上使用也是非常的合适。在API上借鉴了ActionScript的E4X实现,例如获得子节点和属性的方法:

var XML = jsxml.XML;
var xml = new XML("MY-XML-STRING");
//查询子节点,属性
var attValue = xml.descendants('item').child('tagName').child(0).attribute('att-key').toString();

详细的文档请看github.

这里是两个线上的例子:

Posted in Develop & Design. Tags: . 没有评论 »

使用YQL跨域

以前对跨域资源共享做过一些调查,并得出了一些结论,最近用过几次YQL (Yahoo! Query Language),发现YQL也算是一个很成熟的跨域方式,而且也非常的简单易用,对于个人的应用混搭更是再适合不过了。

YQL使用了类似SQL的语法,比如我要拿到某个网页的内容,需要这样去查询:

SELECT * FROM html WHERE url="http://www.colorhook.com/blog"

还可以加上XPATH限定条件来获得指定节点的内容。例如拿到id为header的div中的内容:

SELECT * FROM html WHERE url="http://www.colorhook.com/blog" AND xpath="//div[@id='header']"

YQL集成了一些常用的服务,包括weather, flickr, twitter, map等等。下面看看如何使用YUI来呼叫一个YQL服务。

YUI().use('yql', function(Y){
      Y.YQL("select * from weather.forecast where location='CHXX0044'", function(r){
             console.log(r);
      });
});

这个获取杭州天气的完整源码请看github.

同步新浪微博到人人网

在twitter禁用Basic Authentication,而全面启用OAuth之后,我的Adobe Air版twitter客户端TwitterAir就被搁浅了。转用新浪微博也有一段时间了,今天突然神经抖动了一下,就用PHP写了段同步脚本对人人网做一下同步。同步脚本就不贴在这里了,有兴趣的去这里拿:https://github.com/colorhook/code-snippet/blob/master/php/sina2renren.php

TwitterAir一样,更新状态到人人网的方法使用了XMPP协议。ActionScript的使用案例可以看这里:

使用seesmic-as3-xmpp更新renren状态

写完脚本后,本地能无障碍地跑通,小小地兴奋一下,当部署到博客空间上后就令人沮丧了,tcp端口5222不可用,导致XMPP连不上人人网。鉴于这个原因,只能在localhost上耍耍了,于是再额外写一段js,在本地用node跑起来,并每分钟更新一次:

var http = require('http');
 
var sendRequest = function(){
	var client = http.createClient(80, 'localhost');
	var request = client.request('GET', '/一段省略的PATH/sina2renren.php',
	  {'host': 'localhost'});
	request.end();
 
	setTimeout(sendRequest, 1000 * 60)
};
sendRequest();

使用Three.js制作全景特效

Three.js是目前一个基于JavaScript的比较完整的3D引擎,虽然关注着,但没什么尝试。好久没更新blog了,今天一定要更新一下,就拿Three.js来练手,做一个3D交互全景吧。

制作3D交互全景,首先需要准备一张用于球面的贴图,这里可以用正方体和6张贴图也可以制作全景,但是球面+1张贴图明显更酷,并且相比6张贴图,1张图能节省5个HTTP请求。

制作3D应用的一般需要建立场景,视窗,摄像机,3D模型,材质。例如:

下面看看如何使用Three.js来创建这些东西:

var camera, scene, renderer, object;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
//初始化3D场景
function init() {
	var container = document.getElementById( 'container' );
	camera = new THREE.Camera( 50, window.innerWidth / window.innerHeight, 1, 2000 );
 
	scene = new THREE.Scene();
	var material = new THREE.MeshBasicMaterial({
		map: THREE.ImageUtils.loadTexture( 'sphere.jpg' )});
	object = new THREE.Mesh( new THREE.Sphere(100, 20, 20),  material);
	object.doubleSided  = true;
	scene.addObject( object );
 
	renderer = new THREE.CanvasRenderer();
	renderer.setSize( window.innerWidth, window.innerHeight );
	container.appendChild( renderer.domElement );
 
	document.addEventListener( 'mousemove', onDocumentMouseMove, false );
}
 
function animate() {
	requestAnimationFrame( animate );
	render();
}
//更新鼠标位置变量
function onDocumentMouseMove( event ) {
	mouseX = event.clientX;
	mouseY = event.clientY;
}
//更新相机位置,重绘3D场景
function render() {
	camera.useTarget = false
	camera.rotation.y += (mouseX-windowHalfX)/10000;
	camera.rotation.x -= (mouseY-windowHalfY)/10000;
	if(camera.rotation.x <= -90){
		camera.rotation.x = -90;
	}else if(camera.rotation.x >= 90){
		camera.rotation.x = 90;
	}
	renderer.render( scene, camera );
}
//entry point
init();
animate();

代码量还可以接受,赶紧点击这里查看demo,have fun。

不支持canvas导致demo无法运行的用户请主动更换或升级浏览器。

Page optimized by WP Minify WordPress Plugin