《众妙之门 JavaScript与jQuery技术精粹》 - 读书笔记总结[无章节版][1-60]
近期,反复思考后,还是把所有的笔记通过随笔的方式整理出来放在论坛里,可以让自己对学过的知识有个比较系统而清晰的呈现;
同时,为以后用到相关的知识点做一个整理和查阅。
(一)JSON-P 的实例代码展示
1 <div id="delicious"></div> 2 <script type="text/javascript"> 3 // 可以在JavaScript中直接使用JSON,并且封装在函数调用中时,可作为API的返回值。 4 // 这称为JSON-P格式,被很多API函数支持。可以使用数据端点在脚本语句中直接返回JSON-P格式。 5 function delicious(o){ 6 var out = "<ul>"; 7 for(var i=0; i<o.length; i++){ 8 out += '<li><a href="' + o[i].u + '">' + o[i].d + '</a></li>'; 9 } 10 out += '</ul>'; 11 document.getElementById('delicious').innerHTML = out; 12 } 13 // 这里调用了delicious Web服务来获得最新的JavaScript书签(JSON格式),然后将其显示为无序列表。 14 // 其实,JSON可能是在浏览器运行中描述复杂数据最轻松的方式了,甚至可以再PHP中调用json_decode()函数。 15 </script> 16 <script src="http://feeds.delicious.com/v2/json/codepo8/javascript?count=15&callback=delicious"></script>
(二)找出一组数字中的最大数
1 <script type="text/javascript"> 2 var number = [3,342,23,22,124]; 3 var max = 0; 4 for(var i=0; i<number.length; i++){ 5 if(number[i] > max){ 6 max = number[i]; 7 } 8 } 9 alert(max); 10 </script> 11 12 <!--可以不通过循环而这样实现--> 13 <script type="text/javascript"> 14 var number = [3,342,23,22,124]; 15 number.sort(function(a,b){return b - a }); 16 alert(number[0]); 17 </script> 18 19 <!--可以利用Math.max()函数,返回一列参数中的最大值--> 20 <script type="text/javascript"> 21 alert(Math.max(3,342,23,22,124)); 22 </script>
(三)利用Math.max()函数解决IE一个小问题
1 <script type="text/javascript"> 2 var scrollTop = Math.max( 3 document.documentElement.scrollTop, 4 document.body.scrollTop 5 ); 6 alert(scrollTop); 7 // 测试浏览器支持的默认属性。只有一个属性有返回值,另一个将是未定义。 8 </script>
(四)利用一个函数将CSS类添加到元素中
1 <div id="div" class="box"></div> 2 <input type="button" value="addclass"/> 3 <script type="text/javascript"> 4 // 经典实例:利用字符串的split()和join()函数,编写addClass()函数。 5 function addClass(elm, newclass){ 6 var c = elm.className; 7 elm.className = (c === '') ? newclass : c + ' ' + newclass; 8 } 9 // 问题是,当需要在DOM元素中添加一个类时,要么是将它作为第一个类添加,要么是将它和一个空格键一起加在已经存在的类前面。 10 // 当删除该类时,也需要删除相应的空格(这在过去更为重要,因为有些浏览器会因为多余的空格报错)。 11 var button = document.getElementsByTagName('input')[0]; 12 var div = document.getElementById('div'); 13 button.onclick = function(){ 14 addClass(div, 'box2'); 15 } 16 // 这个方法的缺点:无法只能判断是否已有新的class类,只会无限制的添加。 17 </script> 18 <script type="text/javascript"> 19 function addClass(elm, newclass){ 20 // 把字符串转成数组 21 var classes = elm.className.split(' '); 22 classes.push(newclass); 23 // 把数组转成字符串 24 elm.className = classes.join(' '); 25 } 26 var button = document.getElementsByTagName('input')[0]; 27 var div = document.getElementById('div'); 28 button.onclick = function(){ 29 addClass(div, 'box2'); 30 } 31 </script>
(五)事件代理描述
1 <h2>Great Web resources</h2> 2 <ul id="resources"> 3 <li><a href="http://opera.com/wsc">opera web standards curriculum</a></li> 4 <li><a href="http://sitepoint.com">sitepoint</a></li> 5 <li><a href="http://alistapart.com">A list Apart</a></li> 6 <li><a href="http://yuiblog.com">YUI Blog</a></li> 7 <li><a href="http://blameitonthevoices.com">Blame it on the voices</a></li> 8 <li><a href="http://oddlyspecific.com">Oddly specific</a></li> 9 </ul> 10 <script type="text/javascript"> 11 // 通常事件处理程序是在整个链接中使用循环: 12 (function(){ 13 var resources = document.getElementById('resources'); 14 var links = resources.getElementsByTagName('a'); 15 var all = links.length; 16 for(var i=0; i<all; i++){ 17 // Attach a listener to each link 18 links[i].addEventListener('click',handler,false); 19 } 20 function handler(e){ 21 var x = e.target; // get the link that was clicked 22 alert(x); 23 e.preventDefault(); 24 } 25 })(); 26 </script> 27 28 <script type="text/javascript"> 29 // 也可以通过一个事件处理程序来实现:利用了事件冒泡机制 30 (function(){ 31 var resources = document.getElementById('resources'); 32 resources.addEventListener('click',handler,false); 33 function handler(e){ 34 var x = e.target; 35 if(x.nodeName.toLowerCase() === 'a'){ 36 alert('Event delegation: ' + x); 37 e.preventDefault(); 38 } 39 } 40 })(); 41 </script> 42 <script type="text/javascript"> 43 // 说明:以上例子在IE6浏览器中会运行失败。对于IE6,需要使用事件模型而不是W3C,这就是我们在这种情况下使用库的原因。 44 // 这种方法的好处在于,可以使用单独的事件处理程序。例如,想要在列表中动态地进行添加操作,如果使用事件代理(即事件冒泡到父级), 45 // 则不需要进行任何改变,只需要在事件处理过程中重新分配处理程序,并对列表重新进行循环操作就可以了。 46 </script>
(六)匿名函数和模块模式
1 <script type="text/javascript"> 2 // JavaScript最令人烦恼的事情是变量的范围没有定义。任何在函数外定义的变量、函数、数组和对象都是全局的,这意味着相同页中的其他脚本都可以进行调用,因而经常出现参数被覆盖现象。 3 // 解决办法就是将变量封装在一个匿名函数中,在定义完函数后立即调用。 4 </script> 5 6 <script type="text/javascript"> 7 // 1.先来生成3个全局变量和2个全局函数 8 var name = 'Chris'; 9 var age = '34'; 10 var status = 'single'; 11 function createMember(){ 12 // [...] 13 } 14 function getMemberDetails(){ 15 // [...] 16 } 17 // 该页中其他的脚本如果含有名为status的变量的话就会出问题。如果将它们封装在名为myApplication的匿名函数中,就可以解决这个问题了。但是这样定义使得参数在函数外不起作用,如果这正是所需要的,没有问题。 18 var myApplication = function(){ 19 var name = 'Chris'; 20 var age = '34'; 21 var status = 'single'; 22 function createMember(){ 23 // [...] 24 } 25 function getMemberDetails(){ 26 // [...] 27 } 28 }(); 29 // 另外,可以省略定义的名字: 30 (function(){ 31 var name = 'Chris'; 32 var age = '34'; 33 var status = 'single'; 34 function createMember(){ 35 // [...] 36 } 37 function getMemberDetails(){ 38 // [...] 39 } 40 })(); 41 </script> 42 43 <script type="text/javascript"> 44 // 2.如果需要部分变量或函数可被外部调用,则需要这样改写程序,为了可以调用createMember()或getMemberDetails()函数,将它们作为myApplication的属性返回: 45 var myApplication = function(){ 46 var name = 'Chris'; 47 var age = '34'; 48 var status = 'single'; 49 return { 50 function createMember(){ 51 // [...] 52 }, 53 function getMemberDetails(){ 54 // [...] 55 } 56 } 57 }(); 58 // myApplication.createMember() and myApplication.getMemberDetails() now works. 59 // 这种用法被称为模块模式或单例模式。Yahoo用户接口函数库YUI中经常使用它。 60 // 如果要从一个方法中调用另一个方法,还必须在调用时加上myApplication前缀,因此,我更倾向于返回这些我想要其成为全局元素的元素的指针,这样还可以缩短外部调用时的使用长度。 61 </script> 62 63 <script type="text/javascript"> 64 // 我将这种方法称为 “揭示模块模式”。 65 var myApplication = function(){ 66 var name = 'Chris'; 67 var age = '34'; 68 var status = 'single'; 69 function createMember(){ 70 // [...] 71 }, 72 function getMemberDetails(){ 73 // [...] 74 } 75 return { 76 create: createMember, 77 get: getMemberDetails 78 } 79 }(); 80 // myApplication.create() and myApplication.get() now work. 81 </script>
(七)跨浏览器的事件监听器方法
1 <!--Stoyan Stefanov 的添加和删除跨浏览器的事件监听器方法--> 2 <!--作者在他的《JavaScript Patterns》一书中有介绍--> 3 <script type="text/javascript"> 4 // utils:实用工具 5 var utils = { 6 addListener: null, 7 removeListener: null 8 }; 9 // the implementation 10 if(typeof window.addEventListener === 'function'){ 11 utils.addListener = function(el, type, fn){ 12 el.addEventListener(type, fn, false); 13 }; 14 utils.removeListener = function(el, type, fn){ 15 el.removeEventListener(type, fn, false); 16 }; 17 } else if (typeof document.attachEvent === 'function'){ 18 utils.addListener = function(el, type, fn){ 19 el.attachEvent('on' + type, fn); 20 } 21 } 22 </script>
(八)数组长度缓存的重要性
1 <script type="text/javascript"> 2 // 数组长度缓存的重要性!!! 3 for(var i=0; i<myArray.length; i++){ 4 /* do stuff */ 5 } 6 // 对长度进行缓存可以比反复访问它快上190倍。-Nicholas C.Zakas 7 </script> 8 9 <script type="text/javascript"> 10 // 以下是对数组长度进行缓存的一些方法: 11 /* cached outside loop */ 12 var len = myArray.length; 13 for(var i=0; i<len; i++){ 14 15 } 16 17 /* cached inside loop */ 18 for(var i=0, len=myArray.length; i<len; i++){ 19 20 } 21 22 /* cached outside loop using while */ 23 var len = myArray.lenght; 24 while(len--){ 25 26 } 27 </script>
(九)JSON.stringify()把对象转换成JSON字符串
1 <!-- 2 JSON.parse() 把严格的json字符串,转换成对象 3 JSON.stringify() 把对象转换成json字符串 4 --> 5 <script type="text/javascript"> 6 var myDate = {}; 7 myDate.dataA = ['a', 'b', 'c', 'd']; 8 myDate.dataB = { 9 'animal': 'cat', 10 'color': 'brown' 11 }; 12 myDate.dataC = { 13 'vehicles': [{ 14 'type': 'ford', 15 'tint': 'silver', 16 'year': '2015' 17 },{ 18 'type': 'honda', 19 'tint': 'black', 20 'year': '2012' 21 }] 22 }; 23 myDate.dataD = { 24 'buildings':[{ 25 'houses':[{ 26 'streetName': 'sycamore close', 27 'number': '252' 28 },{ 29 'streetName': 'slimdon close', 30 'number': '101' 31 }] 32 }] 33 }; 34 console.log(myDate); // Object 35 var jsonDate = JSON.stringify(myDate,null,4); 36 console.log(jsonDate); 37 // 额外的调试小技巧,如果你想要使得终端控制台显示的JSON更为美观可读,可以使用stringify()函数的以下额外参数实现: 38 console.log( 39 JSON.stringify({ 40 'foo': "hello", 41 'bar': "world" 42 },null,4) 43 ); 44 </script>
(十)针对命名空间变量存在性的检查
1 <script type="text/javascript"> 2 // 针对命名空间变量存在性的检查: 3 /* 无效检查 */ 4 if( !MyNamespace ){ 5 MyNamespace = {}; // 如果MyNamespace变量之前未经声明,那么!MyNamespace会报错:RefernceError. 6 } 7 /* 有效方式 */ 8 if( !MyNamespace ){ 9 var MyNamespace = {}; 10 } 11 // or 12 var MyNamespace = MyNamespace || {}; 13 // or 14 if( typeof MyNamespace == 'undefined'){ 15 var MyNamespace = {}; 16 } 17 </script>
(十一)关于JavaScript的十个古怪之处和秘密
1 <script type="text/javascript"> 2 // 1.Null 是一个对象 3 alert(typeof null); // object 4 alert(null instanceof Object); //false 5 </script> 6 7 <script type="text/javascript"> 8 // 2.NaN 是一个数字,并且NaN不等于自身 9 alert(typeof NaN); // number 10 alert(NaN === NaN); //false 11 </script> 12 13 <script type="text/javascript"> 14 // 3.空数组 == false 15 alert(new Array() == false); // true 16 // 空数组非常奇特:它们实际上等于true,但是在和布尔值比较时,却被看做false 17 var someVar = []; // empty array 18 alert(someVar == false); // true 19 if(someVar){ alert('hello') }; // alert runs 20 // 为了避免强制类型转换,我们使用值、类型比较符 "===" 21 var someVar = 0; 22 alert(someVar == false); // true 23 alert(someVar === false); // false zero is a number, not a boolean 24 // 如果你想更深入地了解JavaScript比较两个数值的内部原理的话,请查看文件说明书 ECMA-262 的11.9.2节。 25 </script> 26 27 <script type="text/javascript"> 28 // 4.正则表达式replace()函数可以接受回调函数 29 alert('10 13 21 49 32'.replace(/d+/g,'*')); // replace all numbers with * 30 // 如果我们想要控制只替换30以下的数,怎么做 ? 31 alert('10 13 21 49 32'.replace(/d+/g,function(){ 32 return parseInt(match) < 30 ? '*' : match; 33 })); 34 </script> 35 36 <script type="text/javascript"> 37 // 5.正则表达式不仅仅是比较和替换 38 // test()函数比较有趣,它和比较工作方式相同但它并不返回比较值:它只确认类型是否匹配,这样会使计算更轻便。 39 alert(/w{3,}/.test('Hello')); // false 40 // 动态模式 41 function findWord(word, string){ 42 var instanceOfWord = string.match(new RegExp('\b'+word+'\b', 'ig')); 43 alert(instanceOfWord); 44 } 45 findWord('car', 'Carl went to buy a car but had forgotten his credit card.'); 46 </script> 47 48 <script type="text/javascript"> 49 // 6.你可以伪造范围 50 var animal = 'dog'; 51 function getAnimal(adjective){ 52 alert(adjective +' '+ this.animal); 53 } 54 getAnimal('lovely'); // lovely dog 55 56 var myObj = {animal: 'camel'}; 57 getAnimal.call(myObj, 'lovely'); // lovely camel 58 </script> 59 60 <script type="text/javascript"> 61 // 7.函数可以执行自身 62 (function(){ 63 alert('hello'); 64 })(); 65 66 var someVar = 'hello'; 67 setTimeout(function(){ alert(someVar); }, 1000); // goodbye 68 var someVar = 'goodbye'; 69 70 var someVar = 'hello'; 71 setTimeout((function(someVar){ 72 return function(){ alert(someVar); } // hello 73 })(someVar),1000); 74 var someVar = 'goodbye'; 75 </script> 76 77 <script type="text/javascript"> 78 // 8.火狐读取和返回RGB格式,而不是十六进制 79 var ie = navigator.appVersion.indexOf('MSIE') != '-1'; 80 var t = document.getElementsByTagName('title')[0]; 81 alert(ie ? t.currentStyle.color : getComputedStyle(t,null).color); 82 </script> 83 84 <script type="text/javascript"> 85 // 9. 0.1 + 0.2 !== 0.3 86 // 这类问题涉及机器精读的概念 87 </script> 88 89 <script type="text/javascript"> 90 // 10.未定义可以被定义 91 var someVar; 92 alert(someVar == undefined); // true 93 </script>