语音大表
曲刚老师整天在折腾,我感觉他唯一有价值的东西就是这张大表了。
初到北京时我的洗面奶和洗发水丢了,最后又找到了,于是我写了一篇 关于洗面奶和洗发水 ,说北京让我刮目相看了。不愧是北京。
过了几个月,我的笔记本电脑又丢了。我报了警,备了案。平生第一次进了派出所。但是我再也不想写关于笔记本写任何东西。今天
关于这两件事儿有点作想打几个字的冲动,我一向不喜欢废话,就直接给它下个结论吧。同样是丢东西,但两件事儿的性质是完全不
一样的,但我相信不管是在北京,还是在国内任何一个城市,我这样处理的结果都是一个样子的,洗面奶和洗发水会物归原主,笔记
本电脑只会是永远也找不回来。除非你非常幸运。。。
北京无贼?河北无贼?北京无骗?河北无骗?
郑州有贼,河南有贼。郑州有骗,河南有骗。
中国无贼?中国无骗?
这类鬼事儿没有地域界限。。。
常听人抱怨现实生活窘迫,找不到好工作,没有好的收入,房价又太高,现在的女孩太现实,诸如此类。。。
有一次又听一同事又在吐槽,实在听不下去了,我只好给他说了一个实例。
话说有一不差钱的boss许诺只要你跟他混5年,五年过后他愿意给你一套价值100W房子,再给你配一部不错的车,如过你是泡妞。
说不定老板的女儿会被你泡到手,但是三年中你必须任劳任怨,受尽白眼儿,随听随到,打不还手骂不还手,然后他问我,
那我不是要被boss搞死了?为了打消他的顾虑我又补充一句,当然打骂啊什么的都不会太过分,稍微强点儿的人都可以接受的。
我问他愿意不愿意为跟这样的boss拿自己的5年青春做赌注?他很happy的说傻子才不愿意。
与是我告诉他现在还有另一种活法儿:大家都知道只要你对某个行来感兴趣,你投入5年的时间去朝着一个方向拼命努力即使不能
得到上一种活法儿一样的等量价值你也肯定收入不会少于2W/M,这样虽然你和有钱人差距依然很大,但你至少应该不会再抱怨收入太低了。
我又问他你愿意放弃刚才的选择,重新选择这样靠自己的努力而取得不错的收入吗?结果他不干了。
同样的问题我问了许多同事,结果答案是一样的,大家都只愿意选择第一种活法儿。
var a = {
b:1
};
var x = [];
function change(){
var i = 0;
do{
a.b = i;
x.push(a);
console.info('the ',i,'x',x);
i++;
a.b = i;
}while(i<5)
};
change();
console.info('final x',x);
有很多关于Linux的书籍,博客。大多数都会比较“粗暴“的将一大堆的命令塞给读者,从而使很多人望而却步。未入其门就路过了。
所以我设想用一种更为平滑的学习方式, 就是在学习命令时,先用纯语言来介绍Linux背景和动机。 就如同所有的的网络游戏都要先介绍游戏的历史观,然后再介绍游戏的操作。
大多数初学者在刚刚接触Linux都会有非常陌生的感觉。往往会有一些疑惑和问题。而我们就沿着这些问题,从远及近,从宏观到微观来理解Linux的简洁和美丽。
问题1: Winows有注册表,为什么Linux没有注册表
注册表是Windows核心组件,对整个系统进行配置。Linux是以整个文件系统作为”注册表“,Windows注册表的树形结构,可以粗略的对应Linux文件系统的树形结构。
Linux的配置文件就相当于注册表的键,或者说Linux采用是的分布式的注册表。
那么Linux为什么要这样设计呢?因为Linux是所谓的网络操作系统,所以单台电脑不是Linux的界限,如果是多台电脑组成的系统,那么分布式的管理就有着巨大的优势。
例如:一个包含配置文件的磁盘的损害不会让整个系统瘫痪,而可能只是让部分功能失效。
问题2:Windows有完善的图形界面,而Linux为什么要学命令行。
首先,命令行绝对要比图形界面先进的多。命令行是程序员的第一界面,而图形界面是普通用户的第一界面。
也许很多人会有不同意见,其实我们再向前想一步,就很清楚了。
命令行的下一步演化是什么? 很简单就是语音控制,就是把人类自然语言转化为命令
图形界面的的下一步演化是什么? 是姿势控制。从目前的Windows系统来说一共只有3种姿势, 单击,双击,拖放。而更先进的IPad有拨动,画圈等。
姿势控制很简单,便于用户上手,语音控制很复杂,但是控制精度很高。
作为程序员我们要求电脑完成的工作要比普通用户复杂的多,所以使用命令行会非常高效。
退一步讲,图形界面本质也是命令行,只不过将姿势翻译成命令执行而已。
程序员编程的代码也都是“命令行”,一条一条的指令而已。
总之,只要能打破对Linux命令行的恐惧感,接下来的事就会非常容易了。这个命令行绝对不是你简单想像中的命令行,它是非常智能化的。
问题3:Linux有那么多目录,那么多命令,怎么记得住呢?
首先,Linux目录是Linux系统最灵魂的东西,所有的硬件都可以被抽象为文件,从而实现网络化。(Internet只不过是Unix/Linux的进一步的演化而已)
所以只要掌握了Linux目录的规律,在理解的基础上记忆就可以容易的多。另外Linux的命令行有智能化功能,可以让你少打95%以上的字符来完成命令。
绝非你所想象的傻乎乎的敲一大堆命令,那些用Linux大牛都是绝顶聪明的人,怎么可能让自己辛苦呢?
问题4:Linux的文件夹结构看上去很复杂,怎么理解呢?
我们这里假设,我们就是设计者,如果我们设计一个文件系统,我们会如何去做呢?
我们需要一个起点, 这个起点就叫根目录,用“/”来表示,然后我们需要启动Linux,那么我们就会把所有核心的启动文件(包括Linux核心本身)都放到一个“/boot”目录下。
当系统启动后,我们需要执行一些基本命令在操作系统,这些命令都会放到“/bin”目录下。然后这些命令可能会用到一些库,这些库就被放到“/lib”下面,而这些库可能会会用到一些设备驱动文件,
那么这些驱动文件就会放到“/dev”目录下。
/:根目录
/boot:系统启动和内核
/bin :系统基本命令 (bin是binary的缩写)
/lib : 系统库(不能直接运行的代码)(lib是libary的缩写)
/dev : 设备驱动 (dev是device的缩写)
到目前为止只用5个目录,很简单吧。
问题5: 什么是”/usr” ,”/etc”和“/var“
当用户启动系统以后,要做一些更加复杂的工作,这时候就会涉及到一个叫“/usr”,这个情况稍微有些复杂,是一个难点。不过也很容易解释清楚。
早期的unix系统都有很多块硬盘,当时硬盘的容量都很小, 所以往往一个硬盘只放一个目录,比如“/boot”可以放在一个单独的”boot”盘上,上面提到的5个目录,是系统运行必不可少的。
而当系统启动以后,我们需要其他一些用于具体工作的程序时,我们就会加载一个“/usr”目录,上面放重要的运行程序。
容易引起疑惑的是”usr”这个名字, 在历史上,原来这个确实是user的缩写,不过现在和user没有任何关系了, 你可以把它看成是”universal software resource”的缩写。
这个“/usr”有点类似Windows里面的Program Files。
因此 /bin 和 /usr/bin的区别,就是 /bin里面的程序更加核心
这时候,很多人会有疑问, 我们记住哪些命令在/bin 还是在/usr/bin呢?
放心,由于所有的bin目录都会登记到系统变量PATH里面, 因此无论你在任何当前目录中,只要输入命令文件的名称,系统都会帮你找到这个命令并运行。
要点:
1,/usr上面一般都是只读文件,数据文件和配置文件不放在上面(放到哪里,后面会讲)
2,没有“/usr”,linux系统也能正常运行
2,/usr可以被多台电脑共享(这里体现Linux系统的网络性)
由于/usr只放只读文件,那么配置文件和数据文件放哪里呢?这里就出现了2个新的目录“/etc”和“/var”
这里容易初学者迷惑的就是这个2个目录的名字。
在历史上 “etc“是 “etcetera”,中文意为“其他”, 现在这个和“其他”没有任何关系, 就是专门存放配置文件的地方,可以理解为“editable text configuration”的缩写
比如 /etc/mysql就是放mysql的配置文件 /ect/apache2/就是apache2的配置文件
在历史上“var” 是 “variable”,中文意为“变动”,现在主要用来存放log,lock等文件。
例如 /var/mysql就是用来存放mysql的log
问题6:用户自己产生的数据放到哪里?
当我们运行程序后,会产生很多自己的成果,这些成果放哪里呢? 这里就出现了一个“/home”目录,不过你不能直接放到“/home”目录下, 因为Linux是个多用户操作系统, 所以系统会有一个以用户的名字命名的目录。
例如:用户是jack ,那么目录就是/home/jack ,这个目录也可以用“~“来表示。
至此,我们也就基本了解了Linux的组成。
出处:http://blog.csdn.net/lanman/archive/2011/01/21/6156237.aspx
上一篇博文我列出了Qwrap的三个算子:mul,rwrap,methodize,这里我们来说说Qwrap的一个核心设计思路,什么是Qwrap?就是百度有啊前端开发人员在月影的带领下经过长期开发总结的之么一套javascrpt设计方案.
里面提到不污染prototype,之所以强调不污染我感觉是因为之前百度有啊的人在写脚本时大量的在Array,Function的prototype上添加方法,然后就被搞前端开的鄙视了,然后他们通过methodize方法对函数进行变换,解决了这个问题(其它我感觉只是把prototype方法写到了一起了而已,在必要的时候进行批量retouch)
再者近几年jqeury以它的友好的用户接口,和它的低门槛,和完美跨浏览器,blah,blah……总之好处一大堆,其中最让人爽的就是它的链式操作,对元素的选择包装功能了,当然百度的人肯定也会觉得爽,所以他们就想法去实现,直接抄jquery,肯定是被鄙视的.话说月影等人的技术也不是盖的.再者折腾函数本来就是月影的强项,然后他们就提出了wrap概念,所谓wrap就是在一个对象或者属性进行包装,这里提到的对象或者属性被Qwrap称之为core,听着怪吓人的,因为一听到core我就想到系统内核.其实不然,这个核可以是任何东东,比如字符串,一个element对象,一个object,一个数组,一个函数…………等等等等.比如以下例子:
function Wrap(core){
this.core = core;//所谓的core
}
var testCore = new Wrap(document.getElementById('divtest'));
在以上函数Wrap中只有简单的一行,就是this.core被赋值为参数core,接着我们new一个Wrap对象出来赋值给testCore,这时我们就把testCore对象的core属性称之为testCore对象的core(核),这时你肯定会说,到底在讲些什么东西嘛,这有什么好说的,没什么好玩儿的啊.但事实就是这样简单,这里只是提出一个概念.接着他们在这个概念上发扬光大,代码变成下面这样.
function Wrap(core){
this.core = core;//所谓的core
}
Wrap.prototype.getHtml = function(){
return this.core.innerHTML;
}
Wrap.prototype.setHtml = function(value){
this.core.innerHTML=value;
}
var testCore = new Wrap(document.getElementById('divtest'));
你还是觉得没什么了不起的.但概念你一定要知道,一旦确定了一个core,这个对象上主要的方法都应该是为操作core而服务的.”Qwrap”中的wrap就是包的意思,前面那个Q,我想应该理解为core吧.但不确定百度的人到底如何想的…接下来,我们要实现链式操作,Qwrap提出来一个retouch机制,具体是通过methodize方法实现的,我们来看看methodize的源码
function methodize(func,chain){
return function(){
var ret = func.apply(null,[this].concat([].slice.call(arguments)));
return chain?this:ret;
}
};
又是了了几行,我们来看看这个鸟函数能做什么事儿.还是先分析一下它吧.它有两个参数:func(函数),chain(布尔值),返回一个function,被返回的function内部定义一个变量ret,用来接收参数func通过apply执行后的返回值,初学者可能会对这句:[this].concat([].slice.call(arguments))比较费解,其实这句话就是强制把this(当前执行函数的对象)当做函数的第一个参数添加到参数表里去,这就可以做到在操作函数里不进行参数传递,就可以直接操作this对象或者this对象的core(其实如果没有参数core的时候你可以把this理解为core的),因为这句话强制为我们传进来了(不管你用不用,它就在那里).接下来一个三元运算:如果第三个参数chain是true,就返回this(当前执行函数的对象)用于链式操作,否则返回函数返回值(此时不能进行链式操作);来看一个例子吧.
var testa = {
methodA:methodize(function(){
console.log('i am the first func');
return 'first'
},true),
methodB:methodize(function(){
console.log('i am the second func');
return 'second';
},true)
};
//然后我们就可以这样用
testa.methodA().methodB();
//当然也可以这样用
testa.methodB().methodA();
以上就是retouch实例,QWrap里把很多方法放到一个对象里,然后进行批量操作,做到代码与逻辑分开,使其为它的core服务,Arrary,Fucntion,Data,Objcet,STring,RegExp,Number,Boolean,的操作都是如此,有个叫李超的同学写过一篇日志,大家可以看看,地址在这里:http://lichaosoft.net/archives/1223
说到这里我们讲了wrap,methodize,还有一个mul算子,这个mul算子是做什么的呢?
它是为同时操作多个元素服务的,先看代码吧.
//使函数的第一个参数支持数组
//典型用途:对符合条件的多个element进行同时处理,Array,或者Object的map操作
function mul(func){
return function(){
if(arguments[0] instanceof Array){
var ret = []
for(var i=0,len = arguments[0].length;i<len;i++){
r= func.apply(null,[arguments[0][i]].concat([].slice.call(arguments,1)));
ret.push(r);
}
return ret;
}else{
return func.apply(null,arguments);
}
}
};
function testmul(x,y){
return x+y;
}
console.log( mul(testmul)([1,2,3,4],1) );
得到:[2,3,4,5];
依葫芦划飘,如果我们想把两个div的背景色同时设置为red;代码如下
function setColor(el,color){
el.style.background = coloe;
};
//原函数只能设置一个元素,我们把它mul一下
mul(setColor)([el1,el2],'red');
//好了,就这样,实现了.是不是很简单.
Qwrap就是在这些个思想碎片上构造起来的.话说一排排整齐的调用接口下面肯定是一个个龌龊的实现,Qwrap也逃脱不了这句话.
不小心惊动了Qwrap的作者月影,对我对Qwrap理解错误的地方月影悉心纠正,我把他对我对话征得他的同意后放到下面,希望各位同学不要被我误导.
10:31 AM akira.cn: hi~~ 我看了你最近写的关于qwrap的文章,里面的methodize说得其实不是很准确,第二个参数不是chain,链式不是通过methodize来完成的,而且methodize的第二个参数对retouch来说很重要
10:35 AM me: 恩,是的,的确是通过第二个参数…
10:36 AM 不小心惊动了月影大侠,呵呵.
akira.cn: 呵呵~ http://www.silverna.org/blog/?p=211 你看第一段例子代码就明白了,methodize的第二个参数是属性名,它的作用是把function给作为method,然后retouch到Wrap上
10:38 AM me: 是的,retouch到wrap上,但第二个参数,chain不是可以灵活的实现链式调用吗?
10:39 AM akira.cn: 链式调用不一定是返回this的,所以是放在rwrap上实现的
比如selector的链式调用,每次返回的是不同的元素集合,它们是不同的对象,不是同一个this
10:41 AM me: 哦,这可能是我对Qwrap的实现思想不清晰导致的.
10:42 AM 我只是感觉Qwrap好玩儿,还有您写的几个算子,就在那儿瞎鼓捣.
akira.cn: ![]()
10:43 AM me: 回来我再整理一下,我是从一个菜鸟的角度写的.呵呵.
10:44 AM akira.cn: http://www.silverna.org/blog/?p=199 methodize对Wrap其实很重要,不过也只是让methodize多往前走一步,让它不仅仅能对付“this”,而且要能够对付“Wrap”,而且和实际“Wrap”里面的属性是无关的,不管是core还是items或者随便其他什么属性
10:46 AM me: 要这么讲的话,Array其它也是一个Qwrap了
要这么讲的话,Array其实也是一个Qwrap了
10:48 AM akira.cn: 刚才我给你看的第一个例子里,List就是Array的Wrap,我将Array的原生方法给Wrap到List上面去
通过的是methodize(ah, “items”)
10:49 AM 这样List就相当于包装了Array,我扩展方法到List的prototype上,就避免去操作Array的prototype而导致让Array的for..in失效
操作List和Array所有的不同就是必须要new List(arr)
10:50 AM 其他从Array上dump出来的方法都已经retouch到List的prototype上了,所以用它们和直接用Array的方法完全一样
10:51 AM me: 不得不说这套方法的确灵活多变.
10:54 AM akira.cn: 在QWrap里我们把ArrayH.forEach方法给retouch到Array上,让不支持原生forEach版本的浏览器也能用Array.forEach,然后再把它和数组上其他一些方法dump出来给retouch到NodeW上,所以我们就能让NodeW也有forEach等方法,比如可以直接W(“div”).forEach… 这个forEach是直接从数组上“偷”过来用的
10:56 AM me: 我的理解:有了 methodize 实现的retouch机制,QWrap里的方法已经无国界了.
可以到处游荡.
akira.cn: 某种程度上来说是的,不过我们用Helper机制约束了一下
10:57 AM me: 实现一套库.必须要对它的约束,无规矩不成方圆,
10:58 AM akira.cn: 把相同目的方法归类为一个Helper,然后一个一个Helper去retouch,而避免操作零散的一个个方法,那样操作比较乱,也不方便
me: 然后约束是要付出代价的,我感觉这么一约束,就失去了最大的灵活性.
代码也显的难懂了.
10:59 AM 但是为了更好的适应多数开发人员,约束不得不出现了.
akira.cn: 还好,其实也没有失去多少灵活性
11:00 AM 其实QWrap的代码还是很好懂的,其实只要理解了helper.h.js这一个文件,基本上整个核心就OK了
me: 当然,不可能每个开发人员都站在月影的高度去思考问题的.
11:01 AM akira.cn: 我们现在开放出来就是让感兴趣的同学去看代码,这些也不是我们自己说的,都是看代码的同学的体会
me: 前一段时间阿里系一个人问我,为什么Qwrap选择了jquery不一样的实现思路,我无语了…
11:02 AM akira.cn: 其实某种程度上反而是比jquery更好理解,因为jquery里,10个接口可能有10种内部不同的实现,毕竟说让人用起来方便,内部实现就回绕一点,这样读代码就累了
11:03 AM 而qwrap里,只要理解了Helper机制,其实这些变换都就算当做数学公式来背都没问题,在这些变换之上的代码就简单多了
11:04 AM me: 恩,我也有同感,那三个算子理解起来.还是花了我不少功夫的.最后豁然开朗时发现,玩儿的就是函数在玩函数.
玩参数,玩返回值
11:05 AM akira.cn: 是啊,最初设计的时候有6个算子,现在已经减少到3了,而且不会再增加
因为3个已经够了,这种东西还是越少越好
me: 恩,3个很给力.
function mul(func){
return function(){
if(arguments[0] instanceof Array){
var ret = []
for(var i=0,len = arguments[0].length;i<len;i++){
r= func.apply(null,[arguments[0][i]].concat([].slice.call(arguments,1)));
ret.push(r);
}
return ret;
}else{
return func.apply(null,arguments);
}
}
}
function methodize(func,chain){
return function(){
var ret = func.apply(null,[this.core].concat([].slice.call(arguments)));
return chain?this:ret;
}
};
function rwrap(func,wrapper,idx){
idx=idx|0;
return function(){
var ret = func.apply(this, arguments);
if(idx>=0) ret=arguments[idx];
return wrapper ? new wrapper(ret) : ret;
}
}
然后我们可以这样来使用
function $(id){
return document.getElementById(id);
}
function getValue(el){
el.style.background = 'red';
};
function setValue(el,value){
el.innerHTML = value;
return 'hehe';
};
function w(core){
this.tt = core;
return core;
}
function test(core){
this.core = core;
};
test.prototype.set = methodize(rwrap(mul(setValue),w,0),true);
test.prototype.get = methodize(mul(getValue),true);
var ret = (new test([$('id1'),$('id2')])).get().set('-000-');
console.info( ret );
function toRGB(hexColor) {
return {
r: parseInt(hexColor.slice(1, 3), 16),
g: parseInt(hexColor.slice(3, 5), 16),
b: parseInt(hexColor.slice(5, 7), 16)
};
}
function toRGB1(hexColor) {
var matches = hexColor.match(/\w\w/g);
return {
r: parseInt(matches[0], 16),
g: parseInt(matches[1], 16),
b: parseInt(matches[2], 16)
};
}
function toRGB2(hexColor) {
var hex = parseInt(hexColor.slice(1), 16);
return {
r: hex >> 16,
g: hex >> 8 & 0xff,
b: hex & 0xff
};
}
console.info(toRGB('#76400E'));
console.info(toRGB1('#76400E'));
console.info(toRGB2('#76400E'));