第一章,概述
这章是综述性质的,做者随意的给出了一些例子。javascript
1. visibility = hidden, display = none。html
function hide (e, reflow) { if (reflow) { e.target.style.display = "none"; } else { e.target.style.visibility = "hidden"; } }
这段代码展现了两种隐藏节点的方式,以前在项目中接触最多的是display=none,对visibility=hidden的方式没用过,还不知道这种方式和display = none有什么区别。
visibility = "hidden",元素会隐藏,可是不会把元素从渲染树种拿掉,它依然会部分渲染,只是不可见而已(变成彻底透明,只会触发repaint)。
display = "none",那么元素就不会渲染,整个从渲染树中拿掉了。会触发reflow与repaint。
好比 java
中间的元素visibility = hiddennode
中间的元素display = nonegit
其实我想问为何中间那个所谓只会触发repaint的隐藏方式会傲娇的多出来一截。。。。。。显然这种状况下浏览器会reflow的。想一想多是由于我用了自动宽度。果真,这样就和谐多了。
使用固定宽度 github
2. Bind events with DOM node's "on" attributes。正则表达式
给DOM元素定义事件最简单的方法是,给DOM节点以"on"为前缀的属性绑定一个回调。出于页面维护性的考虑,这种代码和HTML节点写一起玩法正常状况下不多会用到。 编程
<div style = "border: 1px solid gray" onmousedown="(function(node){node.textContent = new Date().toString();})(this);">点击我文字会改变</div> <div style = "border: 1px solid gray" onmouseup="(function(event){event.target.textContent = new Date().toString();})(event);">点击我文字会改变</div>
3. addEventListener。数组
玩的更多的应该仍是addEventListener。浏览器
<div id = "click_node">点击我看看</div> <script> window.onload = function() { var node = document.getElementById('click_node'); if (node && node.addEventListener) { node.addEventListener('mousedown', function(){ node.textContent = "mouse down on node"; }, false); node.addEventListener('mouseup', function(event){ node.textContent = "mouse up on node"; }, false); } } </script>
注意几个小问题,好比addEventListener的第一个参数是须要绑定的事件名,全小写的,并且没有”on”前缀。(若是兼容老版IE用attachEvent的话则须要加上on前缀)。第三个参数是用来指定是否把linstener注册在事件的capture阶段,通常都是false,也是使用element.onclick = function(){}这种绑定方式的的默认行为。
关于DOM事件的生命周期,能够参考一下这篇文章。这里插一句,文章中提到经过阻止不必的事件冒泡能够提高性能,不过做者提到的event.cancelBubble这种方式并不被提倡(参考),应该使用event.stopPropagation()来替代这种方式。
第二章,词法结构
这章主要内容是JS程序的词法构成,并无什么须要特别注意的。
1. JavaScript会认为它正在解析的程序代码已是这种标准格式,不会再对标示符、字符串、正则表达式作标准化处理。
关于JavaScript与Unicode,我准备专门再写一篇总结文章。这个Normalization问题有时候挺烦人的,特别是要对字符串作细致处理的时候。ES6已经添加一个新方法String.prototype.normalize来提供这个功能,在此以前可使用一些库来完成,好比unorm (https://github.com/walling/unorm)(by Bjarke Walling).
2. 在return、break、continue语句和随后的表达式之间不能有换行。
不然会出现难以调试的程序问题。正常人应该都不会这么写的。
3. “++”与“--”做为后缀的时候要与表达式在同一行。
同上,正常人不会另起一行写++--的。
第三章,类型、值和变量
1. JavaScript的数据类型分为两类:原始类型(primitive type)与对象类型。简单(原始)类型(simple types)有numbers、strings、booleans、null 和 undefined。剩下的其余的都是对象类型。
注意一下number、string、boolean是类对象(object-like)由于他们有一些预约义的方法,但它们是immutable的。
2. JS不区分整数和浮点数。全部的数字都是双精度浮点数,采用IEEE 754标准。JS中实际的操做(好比数组索引、位操做)则是基于32位整数。
因为是双精度浮点数,因此有喜闻乐见的 0.1 + 0.2 != 0.3。任何采用二进制浮点数的编程语言都会有这个问题。
关于实际操做,好比位操做时使用32位整数, 写代码时能够利用这个特性来把小数转换成整数,参考我这篇文章,《javascript中小数转换为整数》。
IEEE 754 中关于双精度浮点数的规定是1位数符、11位阶码再加上52位的有效数位。因为规范要求小数必须是标准形式,即小数点左边为1,因此用52位有效数字表示了53位的 信息。其所能精确表示的整数范围就是 2^53 ~ -2^53。
3. JS中的NaN有一点特殊:它和任何值都不相等,包括自身。
因此看到dojo库中有这样的equals,也是为了让两个NaN可以“相等”。
function equals(a, b){ return (a === b) || ( a !== a && b !== b); }
其实前面第一条讲类型时已经说过了。
5. JS中有“包装对象”的存在,前面提到的使用简单类型的方法其实是经过建立临时的包装对象,而后再使用包装对象的方法。null和undefined没有包装对象,试图引用他们的任何属性都会抛错。
简单对象虽然看起来有一些属性,好比"123".length, 可是试图给它赋值属性(如"123".attr = 4)会被忽略掉 ("123".attr is still undefined)。
6. JS会在必要的时候把包装对象转换成原始值。如“==”认为原始值与其包装对象相等(包装对象会向原始值转换),可是“===”不会进行任何转换,因此不等。
对象原始值的比较(==)会试图把对象的原始值求出来再比较,若是是两个对象比较,则比较他们是否引用同一个对象。
var a = 'a', b = 'a', c = new String('a'); d = new String('a'); a == b // true
a === b // true a == c // true, 会转换
a === c // false, 全等不转换 c == d // false, 两个对象的比较
c === d // false, 没悬念
7. 对象向原始值的转换有些复杂。显示转换最简单,好比 Number("3"), Object(3)。
有一些经常使用的简单写法
+x //把x转换成Number, 至关于Number(x), 也能够写成 x - 0,不过没+x看起来好看 !!x //估计你们见得多了,至关于Boolean(x)
8. Object to Boolean 全部的对象类型都会转成true。
因此别太惊讶,new Boolean(false)其实是会转换成true。
if(new Boolean(false)) console.info("yes, new Boolean(false) is truthy");
9. Object to Number/String, 涉及到toString(), valueOf()这两个方法,通常状况下转成string,toString会先调用,不行就valueOf;转成number则顺序颠倒。
10. “-“会把它的两个操做数都转换成数字。而对于”+“,不少时候+的操做数会被转换成字符串。
[1] + 1; // ”11“ [1] - 1; //0 new Date() + 1; //"Sun Aug 10 2014 00:20:41 GMT+0800 (China Standard Time)1" new Date() - 1; //1407601216775
11. 关于变量,JS中没有块级做用域,JS是函数做用域。因此有一种”声明提早“的非正式称谓(hoisting)。
实际上JS脚本虽然是解释执行,可是在逐行执行以前还有一个”预编译“的过程,这个过程会把context中声明的变量放入”栈“中,并未他们赋值为undefined,而后再开始逐条执行语句。
体会一下这个例子
a(); function a() { console.info(1);} a(); function a() {console.info(2);} a(); a = function () { console.info(3);} a(); //输出: //2 2 2 3
12. 使用var 声明的变量没法被delete删除,而做为对象的属性能够。
删除一个你本身声明的变量确实没有什么必要。
(function() { var a = '123'; console.info(a); delete a; console.info(a); })(); //输出两个”123“
13. 做用域链与闭包。
这个我决定再单独开一个坑。