2014年10月

关于Git

Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。

Git在线学习工具:
[重磅推荐]:15分钟学习Git:https://try.github.io/levels/1/challenges/1
codeschool上的Git学习教程:http://gitreal.codeschool.com/levels/1
Git分支命令练习:http://pcottle.github.io/learnGitBranching/

Git学习书籍:
Git教程:廖雪峰博客
百度云:看日记学Git(来源:Linux大棚博客)

Git使用教程:
[重磅推荐]:Git Magic
博客园:Git使用教程
博客园:msysGit安装后配置和编码问题解决

NoSQL入门

NoSQL释义:
non-relational或者Not Only SQL,泛指非关系型数据库,它的出现,弥补了关系型数据(如MySQL)在某些方面的不足,在某些方面能极大的节省开发和维护成本。
计算机体系结构在数据存储方面要求具备庞大的水平扩展性(只能够连接多个软硬件的特性,可以将多个服务器从逻辑上看是一个实体),而NoSQL致力于改变这一现状。

NoSQL特点:
易扩展:NoSQL数据库去掉了关系型数据库的关系型特性,数据之间无关系,这样就非常容易扩展。
大数据量,高性能:NoSQL数据库都具有非常高的读写性能,大数据量下同样表现优秀。一般MySQL使用Query Cache,每次表更新Cache就失效,是一种大粒度的Cache,在频繁的web交互中这种cache性能不高。而NoSQL的Cache是记录级的细粒度Cache,所以在这个层面上性能就要高很多了。
灵活的数据模型:NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系型数据库中增删字段是一件非常麻烦的事情,大数据量的表更加糟糕。
高可用:NoSQL在不太影响性能的情况,就可以方便的实现高可用的架构。

NoSQL数据库:

nosql_database.jpg

扩展阅读:

一网打尽当下NoSQL类型、适用场景及使用公司

NoSQL系列文章——孙立:

Java虚拟机运行时数据区

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。

java_runtime_dataarea.png
图1 Java虚拟机运行时数据区

程序计数器:

程序计数器可以看作是当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,为了线程切换后能恢复到正确的执行位置,每条线程都要有一个独立的程序计数器。

如果线程执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令地址;如果执行的是Native方法,这个计数器的值为空(Underfined)。

特点:线程私有,较小的内存空间。
异常状况:无 (Java虚拟机规范中唯一一个没有规定任何OutOfMemoryError情况的区域)。

Java虚拟机栈:

虚拟机执行Java方法时的内存模型:每个方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

局部变量表:存放了编译期可知的各种基本的数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(指向对象起始地址的引用指针,或者指向代表对象的句柄或其他与此对象相关的位置)、returnAddress类型(指向一条字节码指令地址)。
局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要的在桢中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

特点:线程私有,生命周期与线程相同。
异常状况:

  • 线程请求的栈深度大于虚拟机所允许的深度,抛出StackOverflowError异常
  • 虚拟机动态扩展时,如果无法申请到足够的内存,抛出OutOfMemoryError异常

本地方法栈:

和虚拟机栈类似,区别是虚拟机栈为虚拟机执行Java方法服务,本地方法栈为虚拟机执行Native方法服务。有的虚拟机将两者合二为一,如Sun HotSpot虚拟机。

Java堆:

在虚拟机启动时创建,存放对象实例的内存区域。

特点:

  • 所有线程共享
  • Java虚拟机管理的内存中最大的一块
  • 垃圾收集器管理的主要区域
  • 可以处于物理上不连续的内存空间中(逻辑上一致)
  • 堆容量可以动态扩展。

异常状况:如果堆中没有内存空间完成实例分配,并且堆也无法再扩展时,抛出OutOfMemoryError异常

方法区:

和Java堆类似,用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据。

特点:线程共享,垃圾回收行为较少出现。
异常状况:当方法区无法满足内存分配需求时,抛出OutOfMemoryError异常。

运行时常量池:

是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分信息在类加载后进入方法区的运行时常量池存放。

特点:具有动态性,运行期间也可以将新的常量放入常量池中。
异常状况:当常量池无法满足内存分配需求时,抛出OutOfMemoryError异常。

直接内存:

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError异常出现。

JDK1.4加的NIO中,ByteBuffer有个方法是allocateDirect(int capacity) ,这是一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。

异常状况:服务器管理员配置虚拟机参数时,一般会根据实际内存设置-Xmx等参数信息,但经常会忽略掉直接内存,使得各个内存区域的总和大于物理内存限制(包括物理上的和操作系统级的限制),从而导致动态扩展时出现OutOfMemoryError异常。

JavaScript总结

js.png

一、JavaScript语言

1.JavaScript特性
• 高级函数:将函数作为参数;可以返回一个函数。
• 动态类型:晚绑定;可以赋给变量任意类型的值,并可随时更改类型。
• 灵活的对象模型:JavaScript的对象模型使用一种相对不常见的方式进行继承,称为原型;不是Java语言中更常见的基于类的对象模型。

2.作用域、作用域链、闭包
作用域(Scope):作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。
在JavaScript中,变量的作用域有全局作用域和局部作用域两种。

全局作用域(Global Scope):在代码中任何地方都能访问到的对象拥有全局作用域。
以下几种情形有全局作用域:
1)最外层的函数和在最外层函数外面定义的变量拥有全局作用域
2)所有未定义直接赋值的变量自动声明为拥有全局作用域
3)所有window对象的属性拥有全局作用域

局部作用域(Local Scope):和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,所以也被称为函数作用域。

作用域链(Scope Chain):在JavaScript中,函数也是对象,函数对象和其他对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性被称为函数的作用域链,它决定了哪些数据能被函数访问。
1)当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象填充,如this、window、document、函数名等。
2)执行此函数时会创建一个称为"运行期上下文(execution context)"的内部对象,运行期上下文定义了函数执行的环境。每个运行期上下文都有自己的作用域链,用于标识符解析,当运行期上下文被创建时,它的作用域链初始化为当前运行函数的[[Scope]]所包含的对象。
3)在函数的运行过程中,每遇到一个变量,都会经历一次标识符解析过程以决定从哪里获取或存储数据。过程为:搜索运行期上下文的作用域链,从作用域链顶层开始,也就是运行函数的活动对象;如果找到则使用这个标识符,没有则继续搜索下一个作用域链中的下一个对象;如果最后都没有找到则返回undefined。

闭包:闭包就是能读取其他函数内部变量的函数。在JavaScript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的桥梁。
当内部函数 在定义它的作用域 的外部 被引用时,就创建了该内部函数的闭包 ,如果内部函数引用了位于外部函数的变量,当外部函数调用完毕后,这些变量在内存不会被 释放,因为闭包需要它们。
其他说法:
• 闭包是函数和执行它的作用域组合的综合体——《JavaScript权威指南》
• 闭包是一种在函数内访问和操作外部变量的方式
• 所有的函数都是闭包
• 函数可以访问它被创建时上下文环境,称为闭包——《JavaScript语言精辟》
• 内部函数比它的外部函数具有更长的生命周期

闭包应用场景:
• 实现私有成员
• 保护命名空间
• 避免污染全局变量
• 变量需要长期驻留在内存
闭包用处:
• 读取函数内部的变量
• 让这些变量的值始终保存在内存中
使用闭包注意事项:
• 闭包会使得函数中的变量保存在内存中,内存消耗比较大,所以不能滥用闭包,否则容易造成网页性能问题,在IE中可能会导致内存泄漏。解决办法是:在退出函数之前,将不使用的局部变量全部删除。
• 闭包在父函数外部,改变父函数内部变量的值。

参考:学习Javascript闭包(Closure)

3.函数式编程
函数式编程是种编程规范,它将电脑运算视为函数的计算。函数式编程的重点是函数的定义而不是像命令式编程那样强调状态机(state machine)的实现。

JavaScript中函数的特性:
• 函数并不总是需要名称
• 函数可以像其他值一样分配给变量
• 函数表达式可以编写并放在括号中,留待以后应用
• 函数可以作为参数传递给其他函数
JavaScript中函数式编程的一些特性:
• 函数是顶层对象:function是JavaScript中最基础的模块,本身是一种特殊的对象;不依赖与任何其他对象可以独立存在;一切皆是可传入function的值,连function本身也不例外
• 高阶函数:对函数的进一步抽象。如Array.sort(function)是JS引擎提供的一个高阶函数。(传入的function是比较函数,如果没有传入参数,默认通过转换后的ASCII码进行比较)
• 闭包
• 函数柯里化(Currying):在计算机科学中,柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并返回接受余下的参数而且返回结果的新函数的技术。
柯里化就是预先将函数的某些参数传入,得到一个简单的函数。但是预先传入的参数被保存在闭包中,因此会有一些奇特的特性。
• 函数式代码风格:连续运算,如连续赋值(var a=b=c=5;),短路条件(a=a||''; a&&a++;),三元表达式(a>b?a++:a--);链式调用

使用函数式编程的优点:
• 函数内的运算对函数外无副作用
• 便于调试和单元测试
• 编写更加优美的回调
• 高内聚,低耦合的一种体现

二、引擎
1.主流浏览器的JS引擎
JavaScript引擎是一个专门处理JavaScript脚本的软件程序,一般会附带在网页浏览器中。正是由于浏览器JS引擎不同,导致JavaScript的不兼容。
常见的JS引擎有:
V8(chrome),Carakan(opera),JaegerMonkey(firefox),Nitro(safair),Jscript(IE)

2.加载和执行
从源码到可执行代码:编译(complied)——>解释(interpreted)
JavaScript代码执行的过程:语法检查(词法分析->语法分析)——>运行时(预编译->运行)
预编译时:1.将上下文的var申明变量放入"栈"中并赋值为undefiend;2.读入"定义"的函数

常见问题:
判断变量存在:alert(a === undefiend); 推荐:alert(typeof a === 'undefiend');

3.垃圾回收
JavaScript不需要手动的释放内存,它使用一种自动垃圾回收机制(garbage collection)。当一个对象无用的时候,即程序中无变量引用这个对象时,就会从内存中释放掉这个变量。如果两个对象相互引用,没有第三个对象来引用,那么这两个对象也会被回收。

三、Web性能
1.快速响应的用户界面

异步执行JavaScript:Web Worker Web Worker的使用

2.DOM编程
减少Reflow/paint:性能攸关的大事
Repaint:透明度改变;文字颜色变化;背景颜色变化;背景图片变化
Reflow:页面渲染过程中;Dom结构变化;浏览器窗口大小改变;布局变化

javascript_dom_time

优化提升,使用事件代理:
• 避免重复绑定
• 减少事件绑定的处理时间
• 减少内存的使用
• 对新插入的节点不用再次绑定

3.Ajax性能
• 两种主流的请求方式
• 两种发送数据技术
• 数据格式
• Ajax性能指南