茗梓小栈

2015总结

» 2016-01-31

2015年就这么过去了,回顾一下这一年的历程。

15年上半年把耽搁了很久的驾照考出来了,这大概是最值得庆祝的一件事情,因此导致3~6月份过得特别辛苦,一方面想要早点考出驾照,另外一方面又因为练车而特别疲惫,甚至有所抵触。幸运的是3个月顺利考出了驾照,悲催的是,整个人变得又黑又丑又憔悴。

今年做的主要项目是优乐洗和百世店加,期间完成了beyond的雏形,用了一段时间,最后还是决定向react靠拢,向社区靠拢。beyond已经分拆为两部分 beyond-lib和beyond-control,前者已经开始,并发布了2个更新,版本号到0.6 ,后者还没有开始开始更新,预计会做一次较大的更新,主要是功能的添加,版本计划直接到0.5或者0.6。

百世店加的开发历程,我越发感觉项目管理和采用合适技术的重要性。合适的项目管理可以让整个开发流程顺风顺水,而合适的技术可以让开发效率得到大幅度的提高。不过也是因为之前没有研究透webpack的一些部分,所以导致我还是采用了传统的开发模式,在后期开始处理代码压缩合并替换的时候遇到了很多的问题,我整整耗费了两天的时间写了一个脚本来处理这些,但如果一开始就采用webpack,那么就不会有这个问题,可以节约大部分的时间。

年底开始react的组件化,我设想了好多种组件的方案,目前决定下来的是开发效率最大化,在bootstrap和react-bootstrap的基础上进行二次开发,争取达到可以最快速地使用组件。好争取时间来完成一些其他的东西,多研究一些源代码。下半年前端开始研究react,后来因为中途去做了店加商城的项目,直到11月份react相关的研究才开始有所突破,预计后期的研究点要深入到react的源代码和组件编写规范,现在也是在看bootstrap和一些react组件的源码。react+flue的架构模式可以让前端各异的代码风格问题有所缓解,在可维护性上相当不错。但也并不是万金油,在纯展示性的方面,用jQuery+众多插件依然是不错的方法,目前在我看来,react,包括其他的mvvm框架,使用场景还是在数据驱动的业务场景方面。还没有在移动端方面使用react,这一点在16年有必要去尝试一下。

技术方面,每天都有在不断的学习,每天下班的时候会感觉较前一天有所进步,只是这些进步越来越小,同时也不断感觉到自己在碰壁,瓶颈越来越大,有点无法突破,可能也是跟自己懒了有关系吧。自己也会一直去尽力找寻突破点的。

mysql数据表中增加序号(rownum)字段

» 2013-11-25

mysql的数据表定义中,就可以为主键设置自增字段(Auto-increment),但如果表中已经存在数据,那么该如何解决。下面是谷歌出来的结果,只是对于显示而言,可以增加一个序号字段,并不会对原有的数据库表有所影响。

SELECT t.*, 
       @rownum := @rownum + 1 AS rank
  FROM YOUR_TABLE t, 
       (SELECT @rownum := 0) r

但博主这边的需求是要为原有的数据库表增加一个序号字段,原有的数据条数从1,2···开始编号,这个字段就是用来记录这个编号,命名为no。即增加一个字段,然后对这个字段进行update,网上也有很多的方法,博主试验的这个方法,应该来说是比较方便的:只是用到一条update语句。

update my_table t,(SELECT @rownum := 0) r  
set t.no = (@rownum := @rownum + 1)

参考文献

http://stackoverflow.com/questions/1895110/row-number-in-mysql

javascript中函数定义两种方式的加载方式

» 2013-10-26
var foo = function(){};
function foo(){}

以上是javascript中定义函数的两种方式,另外还有一种是通过Function 函数来实现的,但这种用得不多,就不作为讨论了。

此前看过一篇文章,依稀记得文章里讲,说两者其实没有区别,第二种方式只是为了迎合C语言系列程序员的编程习惯而构造出来的语法糖。但这个问题还是在之前的面试中被问到了,我的回答显然让对方并不满意,回来后翻资料的时候恰好看到了一个例子,于是做了一些测试,发现两者其实还是有区别的。

javascript 虽然是一种脚本语言,但引擎在解释代码的时候,还是会有一个“预编译”的过程。这个过程会执行下来的一些操作:

  1. 创建一个当前环境下的活动对象。
  2. 将那些用var申明的变量设置为活动对象的属性,为这些变量赋值为undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值也都是函数的定义。

从上面的信息中可以看出,js是有一个“预编译”的过程,会预先加载function定义的函数,那么如下代码经过测试,是能够正确执行的

foo()  // output:foo has been loaded
function foo()
{
    console.log("foo has been loaded");
}

上述的函数定义显然是符合“预编译”过程中会预先加载function定义的函数这句话的。

那么我们考虑另外一种函数定义方式,见如下代码。

foo()  // output:foo has been loaded or error
var foo = function()
{
    console.log("foo has been loaded");
}

上述的函数定义方式,会产生怎样的结果呢?在chrome30中,错误信息如下:Uncaught TypeError: Property 'foo' of object [object Object] is not a function,显然这种函数的定义方式是符合“预编译”过程中对于用var定义普通变量的规律。

是不是可以这样子理解,第一种函数定义为预加载,而第二种则为运行时加载。

测试环境:chrome30,firefox24,IE7~8

参考

http://hi.baidu.com/chenminliang/item/f87bdfd42dea14332b35c730

两次面试总结

» 2013-10-26

校招投递web前端岗位开发,面试了两次,第一次百度,第二次是网易。一面都基本轻松通过,但都是在最终面的时候挂掉,总结了下自己的不足:

  • 基础不扎实,看多于写。
  • 平时的知识积累过于松散,没有做很系统的总结,在面试的时候就不能完整地表达出来。
  • 心态问题。

讲一下昨天(2013.10.26)网易二面的问题和感受,由于第一个问题就上升到了一个比较高的高度:javascript的内存泄漏。让我有点适应不太来,这个问题虽然之前有看过一些文章,但确是一点也想不起来,这就是没有及时总结的后果。关于这个问题,在我思路清晰的情况下,有以下2种情况会引起内存泄漏,我说出了第二种,但貌似不正确。

1 引起内存泄漏最经典的例子,自循环引用var a = Array(1);a[0] = a,这个在比较旧的浏览器中,特别是ie,会引起内存的泄漏。

2 见以下代码,这种方式会在旧版的ie下引发内存的泄漏,其中我提到这个,但是面试官又问我,这个到底是内存泄漏还是内存积累,我也无言以对。

function Foo()
{
    var p = document.createElement('p');
}
Foo();

接着下面再提到一些的问题

1 javascript性能优化问题(这题平时看过不少的东西,但是当时也直接回答不上来)

2 js的函数提前加载问题(这个我愣了一下没回答上来,悲剧)

3 原型继承的问题(这个我表示,练习的不多,只会最基本的,稍微变化一下就怂了)

4 CSS模块化的问题

5 动画问题,包括CSS3方面和js实现动画(这块就是薄弱项)

然后这些问题,我都回答得很不好,接下来会做一些整理,查漏补缺,总结一句:败乃兵家常事,大侠请重新来过

博客新主题

» 2013-09-23

jekyll默认的博客主题太过于单调,而jekyllbootstrap又过于复杂,而且我着实不太喜欢用bootstrap,html代码嵌套过多,如果不去用第三方主题,外观基本都是千篇一律的。但自己本身也没有很好的美学感,所以就东抄一点,西凑一些。这个背景和导航条的样式,就是从一些网站上抄来的,搭配起来还算大气简洁。

最近小说的框架搭建好了,正在一步步地构思剧情,目前进展到第二回,但是关于男主的名字我又蛋疼了,想不到一个好的名字,下面的剧情就想不下去了。

最近学着一步步把博客转到html5,我发现我的技术,全都停留着html4和css2的时代,已经很久没有去学些新东西了,一直重复着一些无所谓的劳动,看起来是在不断地练习,但实际的技术并没有很好地增长,这是必须深刻反思的一点。

列一下目前博客的一些改进吧

  • 布局全部转向html5的标签,通过引入html5.js来支持ie
<!--[if IE]>
 <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
  • 改善了导航条fixed于顶部的js代码,增强了ie的兼容性
var scrollTop = document.body.scrollTop > 0 ? document.body.scrollTop: document.documentElement.scrollTop;
  • 更换了一个语法高亮的css
  • 增加文章的归档
  • 增加了评论功能,来自于多说

按照目前的进度,假如文章我再写得勤快一点,可以在主页增加分页功能了。

pqframe2 开发构想

» 2013-09-13

pqframe是我花了一年多的时间开发的php的web开发框架,目前框架初步完成,但是这个版本还是很不足,在许多方面都有所欠缺,比如只支持单一数据库,安全性比较弱,不支持url路由等等。但同时这也是一个优点,就是这个框架足够简洁和轻便,容易上手和二次开发,很适合开发中小型站点。

在汲取了1.0版本的开发经验后,我开始构思这个框架的2.0版本。我的计划是,她的构架和1.0是完全不同的,会有一些我自己的创意在里面,也会和1.0版本一样,吸取一些成熟的web框架的优点;以下是我最近构思的一些tips

  • 与时俱进,但考虑中国的国情,支持php5.3+的版本

  • 优秀的调试工具,如rails的rails console 这样子的调试方式

  • 会采用很多成熟的代码,如medoo,确实是个好东西

  • 集成一些常用的类库,但不会做成一个full-stack框架

  • 是否采用命名空间,我还是有点纠结,个人感觉php的命名空很别扭。。。

  • 会采用php的包管理器composer

本文持续更新,但估计2.0版本的开发工作,会比较延期。。。。

window安装版tomcat:OutOfMemoryError解决方法

» 2013-09-09

我们在做一个基于工作流的管理系统,由于这是我接手的第一个java web项目,所以遇到了很多问题,其中一个是 OutOfMemoryError,这算是遇到的比较棘手的一个问题,虽然网上的解决方案众多,但并没有适用我所处的环境。

首先是谷歌到的对于这个问题的解释,千篇一律

PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。

网上解决方法

修改TOMCAT_HOME/bin/catalina.bat(Linux下为catalina.sh)
在“echo "Using CATALINA_BASE:$CATALINA_BASE"”上面加入以下行:

set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128m -XX:MaxPermSize=512m

catalina.sh下为:

JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=128m -XX:MaxPermSize=512m"

我遇到的问题

我安装的是非绿色版的tomcat,在TOMCAT_HOME/bin/目录下面是没有 catalina.* 这个文件的,也就是更改tomcat启动的时候java设置项,这个是可以在gui界面进行设置的,如图 tomcat-gui

增大内存区的参数设置被添加到了java options项里面,然后成功解决这个问题,记得里面的单位 m 一定要小写,上述图中有错误,大写的话,启动会报错。

读书:《javascript 高级程序设计》动态原型继承的一个错误

» 2013-08-31

这是我在复习《javascript 高级程序设计》时候发现的一个问题,书里面讲得不是很易懂,于是我自己查阅了一下资料,了解了一下。以下代码是书中提到的利用动态原型实现继承的一个例子,并说这个例子是有缺陷的,问题代码在以下代码中注释特别标出来的那行的。

function Polygon(iSides) {
    this.sides  = iSides;
    if(typeof Polygon.__init__  === "undefined")
    {
        Polygon.prototype.getArea = function () {
            return 0;
        }
        Polygon.__init__ = true;
    }
}
 
function Triangle(iBase, iHeight) {
    Polygon.call(this, 3);
    this.base = iBase;
    this.height = iHeight;
    if(typeof Triangle.__init__ === "undefined")
    {
        Triangle.prototype = new Polygon();   //这一句是错误的,请注意!!!!!!!!
        Triangle.prototype.getArea = function(){
            return this.base * this.height / 2;
        }
        Triangle.__init__ = true;
    }
}
 
var t1 = new Triangle(2,2);
var t2 = new Triangle(2,2);
t1.getArea();   //Uncaught TypeError: Object #<Triangle> has no method 'getArea'
t2.getArea();   //2

通过对象t1和对象t2的proto 属性可以查看这两个对象所指的原型链,发现这两个原型链指的并不是同一个对象。也就是说t2所指的原型链确实是我们代码中要实现的,而t1并不是我们想实现的,通过查看可以发现t1对象的原型链指向的是一个空对象。发生这种的原因有两个

  1. 在于js对于对象是采用引用的方式。
  2. new Foo 这种方式生成对象时候,js引擎内部的一个处理顺序。

首先是第一个原因,对于以下代码

var a = new Object;
var b = a;
a = null;
console.log(b)   // Object { }

赋予变量a一个空对象,第二行新建变量b,并让b也引用a所引用的那个对象。此时那个空对象有了两个变量引用。第三行让a为null,并不会销毁这个对象,因为b还在引用该对象。

其次是第二个原因,

function Car() {}
car1 = new Car()

对于以上的代码,发生了什么呢,这是developer.mozilla.org上的解释

When the code new foo(...) is executed, the following things happen:

  1. A new object is created, inheriting from foo.prototype.
  2. The constructor function foo is called with the specified arguments and this bound to the newly created object. new foois equivalent to new foo(), i.e. if no argument list is specified, foo is called without arguments.
  3. The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)

简单翻译一下即为:

  1. 一个新的对象被创建,并从foo.prototype 继承(将该对象的proto指向foo.prototype)
  2. 该构造函数,即foo函数被调用,在调用的时候,把函数内部的this变量绑定到了第一步新建的那个对象
  3. 假如这个构造函数没有返回一个对象,则将返回第一步创建的对象

总结一下:
那么我们现在可以解释为什么第一段代码会有问题了,当第一个对象t1被创建时,获得对其构造函数原型的引用,然后再执行构造函数,在构造函数中,该函数的原型重新引用了一个新对象,即Triangle.prototype = new Polygon();但最初Triangle的原型对象还被t1.__proto__所引用着,因此不会被销毁,最终造成t1和t2对象的原型链指向的是不同的对象

css学习心得

» 2013-07-24

前言

作为初学者来说,css最难应对的还是各种浏览器兼容性问题,假如要使你的网页在ie6-9,firefox,chrome 中都呈现完美的视图,还是需要一定的努力和长时间的锻炼的。新手应付兼容性问题,可以使用适当的hack(关于hack,请自行google,这里不详述),但不要依赖hack。有这么一句话:能干的人解决问题,智慧的人绕开问题。这就是我设计css时所遵循的一个原则,避免使用hack,绕开浏览器兼容的性的敏感地带,绕开容易出错的属性,同样的效果,使用不容易出错,最简单的方法来设计。

本心得配合几个实例,希望同学们在看的时候也能实践写写,并在各个浏览器里测试。因本人水平有限,当中不免出现一些错误,不吝赐教。

个人的一些经验

  1. 左右(上下)内边距与宽度(高度)尽量(注意只是“尽量”,不是绝对)不要对一个元素同时设置,这对于以后的维护也是比较方便的。

  2. 某种设计,一般情况下,既可以使用padding,也可以使用margin,个人推荐使用padding,相比margin,由于padding添加不当导致的浏览器兼容问题比较少。但还是应该了解margin和padding使用的场合。

  3. 记住ie6几个臭名昭著的bug,比如“浮动双边距”,“3px”bug,这些bug的解决方法在网上都有。

  4. 使用css重置,虽然这个比较有争议,但是个人推荐使用,能大大减少在浏览器兼容方面调整所浪费的时间。

  5. 有些效果应该根据特定的场合来设计,比如单行文本的垂直居中,可以有以下两种方式:

    • 假如包含这个文本的元素已经设置了固定高度,那么可以为这个元素添加line-height,等于其已经设置的固定高度。
    • 假如包裹这个文本的元素没有设置固定高度,那么可以用上下的相同padding来达到垂直居中。
Fork me on GitHub