HTML5学习笔记 —— JavaScript开发入门
来源:互联网 发布:淘宝卖家为什么改价格 编辑:程序博客网 时间:2024/05/20 06:31
一、注意的规范
1.所有操作符左右需要空格2.每个级别之间一个Tab格3.代码结束之后需要英文分号;4.除了需要输入文字之外,其他所有符号均使用英文引号的使用,自我保持一致
二、JavaScript引入方式
1.JavaScript引入方式分类
a.标签内联b.内部书写c.外部引入
2.JavaScript引入书写方式
a.标签内联 <div class="wrap" onclick="alert('啊啊')"></div>b.内部书写 一般放在标签最后,即</body>的前面 <script type="text/javascript"> alert("啊啊"); alert("我要\n换行"); // 利用\n实现alert弹窗中换行。 </script> JavaScript文件位置很重要,网页自上而下进行代码的运行。 如果JavaScript放置在head标签当中,则会发生错误,如JavaScript效果因无法获取标签而无法运行。 要解决此问题,则需要使用到widow.onload()事件。 将JavaScript文件放置在所有标签后面</body>之前,能够保证网站的全部资源加载完成后再执行JavaScript的内容。c.外部引入 <script type="text/javascript" src="js/test.js" charset="UTF-8"></script> js文件中写入: alert("JS test"); 1)将type、src、charset等属性书写完整 2)外部引入JavaScript的标签之间不允许有其他内容 3)JavaScript文件位置很重要,网页自上而下进行代码的运行。 如果JavaScript放置在head标签当中,则会发生错误,如JavaScript效果因无法获取标签而无法运行。 要解决此问题,则需要使用到widow.onload()事件。 将JavaScript文件放置在所有标签后面</body>之前,能够保证网站的全部资源加载完成后再执行JavaScript的内容。 4)需要引入的JavaScript文件中,不要再出现<script></script>标签
3.JavaScript引入方式优先级
a.外部引入 1)外部引入可维护性最强 2)针对单页面,有代码冗余 3)针对整站来说,外部引入加载速度最快 4)外部引入良好的使用了缓存机制 5)外部引入有可能造成服务器的请求压力b.头部书写 1)针对单页面,头部书写加载速度更快 2)针对整站,存在代码冗余 3)不会造成服务器请求压力 4)代码可维护性一般c.标签内部 1)标签内部书写会存在代码冗余,不便于维护 2)没有很好的实现结构和JS的相分离d.加载速度 1)针对单页面,头部书写加载速度更快 2)针对整站来说,外部引入加载速度更快 3)外部引入有良好的使用了缓存机制 4)外部引入有可能造成服务器的请求压力e.引入方式选择依据 代码量少 → 加载速度快 → 用户体验好
三、DOM操作
1.DOM发展史
此处省略
2.DOM树
3.DOM主要节点
a.标签节点b.属性节点c.文本节点
4.节点的类型
使用nodeType判断节点类型a.标签节点 —— 1b.属性节点 —— 2c.文本节点 —— 3注意:在结构中输入的回车也会被认为是一个节点。d.注释节点 —— 8e.文档碎片 —— 11
5.DOM的节点操作
a.获取节点带()的内容表示方法,如getElementById("demo") 1)通过id名获取标签 getElementById var demo = document.getElementById("demoId"); 2)通过类名获取标签 getElementsByClassName var demo = document.getElementsByClassName("demoClassName"); 兼容性:谷歌、火狐支持、IE不支持 兼容方法: 类库封装 http://www.h5course.com/a/2015042863.html 3)通过标签名获取标签 getElementsByTagName var demo = document.getElementsByTagName("div"); 4)通过属性获取标签 <input type="text" name="ipt" value="获取标签"> var iptEle = document.getElementsByName("ipt"); 兼容性:谷歌、火狐、IE都支持 5)禁止直接用id名进行获取标签 a)JavaScript变量名与id名重复的时候,部分浏览器会发生错误,特别是IE b)要防止id重复 c)后期JavaScript代码不好维护 d)id名与JavaScript属性名一样的时候会出现问题 btn.onclick = function() { alert("我能弹出来嘛?"); } // 可以弹出,但如果设定变量为var btn = 1;就会错误b.获取节点类型 // 获取outerEle的节点类型 console.log(outerEle.nodeType); // 获取outerEle的所有子节点类型 console.log(outerEle.childNodes); // 获取outerEle各个子节点的类型。 console.log(outerEle.childNodes[0].nodeType); console.log(outerEle.childNodes[1].nodeType); console.log(outerEle.childNodes[2].nodeType); console.log(outerEle.childNodes[3].nodeType);c.获取节点的名称 // 获取outerEle的节点名称 console.log(outerEle.nodeName); // 获取outerEle各个子节点的名称 console.log(outerEle.childNodes[0].nodeName); console.log(outerEle.childNodes[1].nodeName); console.log(outerEle.childNodes[2].nodeName); console.log(outerEle.childNodes[3].nodeName);d.针对节点本身的操作:增 删 改 查 1)增加节点 新增节点步骤: 创建节点 —— 添加节点 创建节点: 创建标签节点 document.createElement(标签名); 创建文本节点 document.createTextNode(文本内容); var newEle = document.createElement('h1'); var newText = document.createTextNode('我是文本节点'); console.log(newEle); console.log(newText); 添加节点: appendChild()方法: parentNode.appendChild(node); appendChild方法添加的节点都在原有节点的最后一个。 node是要添加的子节点 // 将文本内容添加到新增标签中 newEle.appendChild(newText); console.log(newEle); // 将新增标签添加到DOM树的outerEle节点中 outerEle.appendChild(newEle); insertBefore()方法: parentNode.insertBefore(newNode, existingNode); // 将新增节点增加到原有outerEle节点中的innerEle标签之前 outerEle.insertBefore(newEle, innerEle); appendChild()方法和insertBefore()方法都是对id的操作,只能操作一次,最后的操作会覆盖之前的所有操作。 2)删除节点 parentNode.removeChild(node); node是需要删除的节点 删除parentNode的子节点中,指定的node节点及其包含的所有子节点,但该方法不能用来删除parentNode孙节点。 // 删除outerEle节点中的innerEle节点,以及innerEle中的所有节点 outerEle.removeChild(innerEle); 删除所有子节点的方法: 因在使用for循环删除所有子节点时,每删除一个子节点,子节点的数量就会边少。 如果采用i++的方法进行操作,则会导致子节点的编号增加后,原本大编号的子节点因为节点数量减少,编号跟着减小而无法被找到。 所以要使用i--的方式进行删除。
<body> <ul id="parentUl"> <li> <a href="#"> <img src="logo.png" alt="" title=""> </a> </li> <li> <a href="#"> <img src="logo.png" alt="" title=""> </a> </li> <li> <a href="#"> <img src="logo.png" alt="" title=""> </a> </li> </ul> <script> var parent = document.getElementById('parentUl'); var child = parent.childNodes; var len = child.length; parent.onclick = function() { for (var i = len - 1; i >= 0; i--) { console.log(i); console.log(parent.childNodes[i]); parent.removeChild(parent.childNodes[i]); console.log(parent.childNodes); } }
3)替换节点 parentNode.replaceChild(newNode, oldNode); 将parentNode中的oldNode用newNode来进行替换,但该方法不能用来替换parentNode孙节点。 outerEle.replaceChild(newEle, innerEle); 4)查找节点 节点关系: childNodes:所有子节点,包括所有类型 console.log(outerEle.childNodes); children:所有是标签类型的子节点 使用children属性获取子集,只可获取子集内的所有元素,而不可制定某种元素如div 如:var boxChi = boxEle.children; console.log(outerEle.children); parentNode:父节点 parentNode只是查找父级,与定位无关,只和DOM树结构有关 console.log(innerEle.parentNode); offsetParent:获取一个元素用来定位的父级 console.log(innerEle.offsetParent); 参考的是有设置position定位( position: relative;和position: absolute;都可以)的上一级(可能是父级,也可能是祖级等等)。 如果没有设置定位,则参考body(实际指的是文档)。 firstChild / firstElementChild:第一个子节点 lastChild / lastElementChild:最后一个子节点 nextSibling / nextElementSibling:下一个兄弟节点 previousSibling / previousElementSibling:上一个兄弟节点 注意:firstElementChild等查找标签节点的方法,只能IE9+支持,IE8-只能利用nextSibling +nodeType进行封装库函数进行查找。 // 输出的是最后一个节点,无论节点类型。 console.log(outerEle.lastChild); // 输出的是最后一个标签节点 console.log(outerEle.lastElementChild); 5)复制(克隆)节点 node.cloneNode(deep); deep为布尔值, true:深复制:复制节点包含其后代的所有各类节点 false:浅复制:只复制本身,不包含其中的所有内容,例如文本节点 IE6~8会复制事件处理程序(用attachEvent绑定方法) 解决办法:先移除事件再克隆e.针对节点属性的操作 1)样式 a)获取标签样式的方法
http://www.h5course.com/a/20150503117.html
function getStyle(eleObj, property) { var proVal = 0; // 因在火狐中有时用window.getComputedStyle获取不到样式,所以该为document.defaultView if (document.defaultView) { // 属性的两种写法 proVal = document.defaultView.getComputedStyle(eleObj)[property]; // proVal = document.defaultView.getComputedStyle(eleObj).property; // .property无效,因传进的参数是字符串,字符串和eleObj对象无关,所以无法使用。但.width的方法是可以使用的 } else { proVal = eleObj.currentStyle[property]; // proVal = eleObj.currentStyle.property; } // 函数的返回值 return proVal; }
b)通过style属性的样式属性操作 changeDiv.style.width = "400px"; c)通过style属性的cssText属性操作 boxEle.style.cssText = "width: 200px;height: 200px;background-color: pink;"
http://www.h5course.com/a/20151107308.html
d)通过类名操作 changeDiv.className = "big"; HTML5-类库制作 类名的各种操作
http://www.h5course.com/a/2015042979.html
2)属性 设置:ele.setAttribute(name, value); 获取:ele.getAttribute(name); 谷歌及IE8+获取类名alert(outerEle.getAttribute('class')); IE6、7获取类名alert(outerEle.getAttribute('className')); // IE6中认为className才对应类名 移除:ele.removeAttribute(name); 3)内容 a)表单元素 value value通常是表单元素的属性,可以进行获取和设置 获取:console.log(firstVal.value); 设置:sumResult.value= parseInt(firstVal.value) + parseInt(secondVal.value); b)标签元素 innerHTML:设置或获取位于对象开始和结束标签内的HTML 即获取<em id="result">200</em>标签内部的内容“200” console.log(sumResult.innerHTML); —— 获取 console.log(sumResult.innerHTML = 600); —— 设置 outerHTML:设置或获取对象(本身)及其内容的HTML形式 innerText:设置或获取位于对象开始和结束标签内的文本 outerText:设置(包含标签本身)或获取(不包括标签)对象的文本
兼容:FF不支持innerText和outerText 区别:在IE6~8 innerHTML和outerHTML获取到的标签均为大写形式(无缩进) IE9+、谷歌、FF会将内容原样输出(包含空格、缩进)返回HTML。 innerText与outerText获取的时候无区别,设置的时候,outerText不仅仅能够替换元素的子节点,还会替换整个元素(节点本身)。<div class="wrap" id="box"> 123 <div>456</div></div> // 这个目的是测试innerHTML获取谁的什么内容? // alert(boxEle.innerHTML); // console.log(boxEle.innerHTML); // // 这个目的是测试innerHTML给谁设置内容? // boxEle.innerHTML = "内容"; // alert(boxEle.outerHTML); // console.log(boxEle.outerHTML); // boxEle.outerHTML = "内容"; // alert(boxEle.innerText); // console.log(boxEle.innerText); // boxEle.innerText = "内容"; // alert(boxEle.outerText); // console.log(boxEle.outerText); // boxEle.outerText = "内容";
四、详解
1.事件的种类
a.一般事件 鼠标、键盘相关b.表单事件 表单相关c.页面事件 与页面有关的事件 举例: load事件 onload网站资源全部下载完成后才出发执行 1)防止JavaScript无法正常获取标签 2)防止JavaScript阻塞页面的渲染 window.onload = function() { var test = document.getElementById("box"); console.log(test); } 3)load事件下定义的变量、函数等,都属于window.onload事件,而不属于全局 JavaScript文件位置很重要,网页自上而下进行代码的运行。 如果JavaScript放置在head标签当中,则会发生错误,如JavaScript效果因无法获取标签而无法运行。 要解决此问题,则需要使用到widow.onload()事件。 将JavaScript文件放置在所有标签后面</body>之前,能够保证加载完html结构后再执行JavaScript的内容。
2.DOM0级事件
a.DOM0级事件绑定方法 1)方法一 对象.on事件类型 = function() { // 里面书写功能代码 } sumBtn.onclick = function() { alert("111"); } 2)方法二 对象.on事件类型 = 方法名; sumBtv.onclick = showResult; function showResult() { alert("222"); }b.DOM0级事件特点 1)书写简单、阅读简单 2)遵循冒泡的运行机制 3)兼容性好 4)绑定多个同种事件类型时,最后的一个会覆盖之前的事件 5)为同一个对象绑定多个不同事件类型,不会发生覆盖,但有可能会同时触发,如单击事件和双击事件。 6)IE中默认在window.even下,需要处理兼容。 测试阻止冒泡是否对DOM0也有用
3.DOM2级事件绑定
a.事件绑定 1)eleObj.addEventListener(事件类型,函数名或者匿名函数,true/false) 第三个参数:true代表捕获,false代表冒泡 兼容:IE9+、FF 2)eleObj.attachEvent(on+事件类型, 函数名/匿名函数); IE10-可以兼容、仅IE11不支持 3)attachEvent方法的this指向问题 attachEvent方法无论在何时何地被调用,他所指向的对象都是window test.attachEvent('onclick', show); function show(){ console.log(this); } // 输出[object] window 4)更改attachEvent方法的this指向 利用call方法修改this指向由window改为触发事件的对象 function addEvent(ele, eventType, handler) { if (ele.addEventListener) { ele.addEventListener(eventType, handler, false); } else if (ele.attachEvent) { ele.attachEvent("on" + eventType, function() { // 修改指向 handler.call(ele); return handler; }); } }b.事件移除 1)eleObj.removeEventListener(事件类型,函数名或者匿名函数,true/false) 第三个参数:true代表捕获,false代表冒泡 兼容:IE9+、FF 2)eleObj.detachEvent(on+事件类型, 函数名/匿名函数); IE10-可以兼容、仅IE11不支持 3)总结:如果addEventListener、attachEvent绑定的事件处理函数是匿名函数,则事件无法移除。 移除事件方法中的参数值与绑定事件方法中的参数值必须保持一致,否则无法移除事件。 如下: outerEle.addEventListener('click', function() { conEle.innerHTML += 1; outerEle.removeEventListener('click', function() { }, false); }, false); 此时需要使用函数名进行移除,如下: outerEle.addEventListener('click', function show() { // 此方法等同于使用匿名函数,不建议使用,会出现无法清除的情况 conEle.innerHTML += 1; outerEle.removeEventListener('click', show, false); }, false); // 使用如下方法 function showInfo() { alert(1); outerEle.removeEventListener('click', showInfo, false); } outerEle.addEventListener('click', showInfo, false);c.事件流 从页面中接收事件的顺序 1)事件冒泡 从最内层的标签事件往外逐步执行,直到执行到document事件 如果某层标签不存在事件,则跳过。 若不存在事件的层级为触发的层级,则执行外层的事件。 注意:IE9+、FF将事件一直冒泡到window对象 兼容:IE9+、FF兼容,执行到window IE8-兼容,只执行到document,不会执行window DOM0支持冒泡。 2)事件捕获 从window对象的事件,逐步向内层标签执行,最后执行点击的最内层的标签的事件。 如果某层标签不存在事件,则跳过。 若不存在事件的层级为触发的层级,则执行外层的事件。 兼容:IE9+、FF IE8-不兼容 3)DOM2级规范是从document开始接收事件,但事实上很多浏览器未按照此规范进行。d.事件对象 ele.onclick = function(e) { } 事件对象存储与事件有关的所有信息,若要实现对标签的操作,需要获取标签,而事件目标对象不需要获取。 在IE8-,用DOM0级绑定的事件方法,认为事件对象是在window.event下,导致通过e参数获取到事件对象e.事件目标对象 IE:e.srcElement document.attachEvent('onclick', function(e) { console.log(e.srcElement); }); FF:e.target document.addEventListener('click', function(e) { console.log(e.target); }, false);f.阻止默认事件 IE:e.returnValue = false; FF:e.preventDefault(); 如下代码会阻止a标签的链接跳转
<body> <a href="http://www.h5course.com/"class="outer-box" id="outerBox"> </a> <script type="text/javascript"> var outerEle = document.getElementById('outerBox'); var innerEle = document.getElementById('innerBox'); var conEle = document.getElementById('con'); outerEle.addEventListener('click', function(e) { e.preventDefault(); }, false); </script> </body>
g.阻止事件冒泡 IE:e.cancelBubble = true; FF:e.stopPropagation(); 表示执行到当前冒泡代码,下一段冒泡代码不执行。 如果e.stopPropagation();放在document中时,冒泡不执行document,但会执行window。 如果e.stopPropagation();放在window中时,window不执行,其他会执行。 如下代码outerEle会弹出,document和window被阻止 window.addEventListener('click', function() { alert('window'); }, false); document.addEventListener('click', function() { alert('第零个'); }, false); outerEle.addEventListener('click', function(e) { e.stopPropagation(); alert('第一个'); }, false); innerEle.addEventListener('click', function() { alert('第二个'); }, false); conEle.addEventListener('click', function() { alert('第三个'); }, false);h.事件委托 原理:事件绑定到父级(祖父、document也行,只要能接收到事件就行)。 利用冒泡的原理,当事件接收到父级的时候,检测目标对象(target/srcElement)。 判断点击的是不是你想要的目标,如果是执行相应的操作。 注意:事件委托只能同一类型事件。 var outerEle = document.getElementById('outerBox'); // 1. 父级绑定事件 outerEle.addEventListener('click', function(e) { // 2. 检测目标对象是否是你想要的 if (e.target.className == "bg") { // 3. 执行相应的操作 e.target.style.backgroundColor = 'red'; } console.log(e.target.nodeName); // 2. 检测目标对象是否是你想要的 if (e.target.nodeName == "P") { // 3. 执行相应的操作 e.target.style.backgroundColor = 'red'; } }, false); 优势: 1)大大减少了事件处理程序的数量,在页面中设置事件处理程序的时间就更少了 (DOM引用减少——也就是我们通过id去获取标签,所需要的查找操作以及DOM引用也就更少了)。 2)document(注:最为推荐的是绑定在document上)对象可以很快的访问到。 而且可以在页面生命周期的任何时点上为它添加事件处理程序,并不需要等待DOMContentLoaded或者load事件。 换句话说,只要可单击的元素在页面中呈现出来了,那么它就立刻具备了相应的功能。 2.1 绑定方面: 如果存在绑定document和父级的情况,在绑定的时候,document在网页加载的时候就会直接绑定事件。 绑定父级的话,需要等父级加载完成之后才可以进行绑定操作,所以绑定的时间会比document慢。 任意时间就可以触发。 2.2 事件的触发(参考): 事件的触发时,如果事件绑定在document上。 同时从点击的对象以上的各级中,未绑定同样事件的时候,事件的就直接冒泡到document,中间的各级都不需要触发事件。 如果绑定在父级上,事件冒泡时,同样遵循一直冒泡到document。 但是在冒泡的过程中,父级会触发事件,触发的过程会造成事件的运行,消耗一定的时间。 所以绑定在document运行时会较快。 3)整个页面占用的内存空间会更少,从而提升了整体的性能。i.兼容库书写 1)事件绑定 2)事件移除 3)事件目标对象 4)阻止默认事件 5)阻止事件冒泡
- 五、函数
1.函数的概念
函数的封装:代码量、性能、维护性、可阅读性强函数用来封装一段可执行代码,可以同时在不同地方进行调用,减少相同代码重复书写,减少代码量,提高运行性能。维护性好,只需要更改函数内部代码,即可实现功能的转换。函数单独封装后,与其他代码分离,提高阅读性。
2.函数的定义语法
function 函数名() {// 功能代码return 返回值}举例// 实现两个数之间的和function sum(start, end) { var sum = 0; for (var i = start; i <= end; i++) { sum += i; }; return sum;}console.log(sum(1, 100));console.log(sum(10, 1000));console.log(sum(100, 10000));
3.形参、实参的概念和区别
实参是具有实际意义,是一个实际的值。形参不具有实际意义,其值在函数调用时再传入,传递参数时形参与实参一一对应(推荐)。若函数的形参名和内部定义的变量名相同时,在定义的变量没有被赋值之前,该变量的值由形参传入,赋值之后,改为被赋值的新值。函数没有对应实参时,默认返回值为undefined。
// 函数的调用/执行:函数名(实参);function sum() { var a = 10; var b = 20; // console.log(a + b); // 函数返回值 return a + b;}// 函数的调用/执行:函数名(形参);function sum(first, second) { return first + second;}console.log(sum(20, 40));
4.arguments
a.arguments是什么 arguments是在函数内部以一个类似数组的形式来存储参数的东西,而这个“东西”是对象,不是数组~ 函数在被调用时,传递进去的参数被保存在arguments对象中(再次强调:类似数组的方式),arguments的长度取决于传进函数的参数个数。 如果传进的参数少于函数定义接收的个数,那么后面的参数视为未定义(即假设函数接收3个参数,如果只传进2个,那么第3个参数值视为undefined)。 如果传进的参数大于函数定义接收的个数,多出来的参数值也会被保存在arguments中,只是在函数执行时,多出来的参数不会被使用。b.arguments的存储规则 1)arguments在函数实参传入时进行创建,此时传入的参数定义了arguments的初始长度。 形参和arguments的一一对应关系在此时建立,之后不可更改。 但形参与arguments的值可以在函数中使用arguments[i] = j;的方式进行添加和修改。
function show (a, b) { arguments[2] = 3; arguments[3] = 4; console.log(arguments); }show(1, 2); // 输出[1, 2, 2: 3, 3: 4]
2)函数传入实参多余定义的形参时,则顺位存储在arguments中,可被输出。
function show (a, b) { console.log(arguments); }show(1, 2, 3); // 输出 [1, 2, 3]
3)函数传入的实参少于定义的形参时,已传入的参数存储在arguments中,同时将已传参的形参和arguments的值一一对应。 未传参的形参不再和arguments一一对应,即再次定义或修改形参的值时,相当于在函数内部另外开辟一个空间存储形参。 而新增加的arguments值,即使其位置与未传参的形参相同,也不再影响未传参形参的值。
function show (a, b, c) { console.log(a); console.log(b); console.log(c); console.log(arguments[0]); console.log(arguments[1]); console.log(arguments[2]); a = 1; b = 2; c = 3; // 运行以上三个赋值语句时,输出11, 22, undefined, 11, 22, undefined, 1, 2, 3, 1, 2, undefined // arguments[0] = 1; // arguments[1] = 2; // arguments[2] = 3; // 运行以上三个赋值语句时,输出11, 22, undefined, 11, 22, undefined, 1, 2, undefined, 1, 2, 3 console.log(a); console.log(b); console.log(c); console.log(arguments[0]); console.log(arguments[1]); console.log(arguments[2]); }show(11, 22);
c.arguments.callee arguments.callee是arguments的属性,表示对函数本身的引用(可以理解为代表的是函数名或函数的地址)。 可用于递归调用,防止函数名变动后由于递归调用时的函数名未手动变更造成错误。
function show () { console.log(arguments.callee); arguments.callee(); }show(); // 无限循环输出 // function show () { // console.log(arguments.callee); // arguments.callee(); // }show(); d.arguments.callee.caller或函数名.caller .caller属性将返回引用当前函数的函数 注意: 1).caller属性只有在应用当前函数的函数被调用时才有效 2)如果当前函数未被其他函数调用时,默认为被最顶层即window调用,则.caller输出null function parent () { child(); } function child () { console.log(arguments.callee.caller); } child(); // 当执行child();时,输出null // parent(); // 当执行parent();时,输出function parent () { child(); }
5.函数的调用/执行
a.函数名后加()即表示调用该函数。b.将函数赋值给变量的方法为,直接将函数名赋值给变量,函数名之后不能加()。若加()则表示将函数运行后的结果赋值给变量c.函数的未书写return时,默认返回值为undefinedd.函数在使用 return 语句时,函数会停止执行,并返回指定的值。e.函数的return语句后,若是一个赋值语句,会在赋值之后,同时将所赋的值做为函数运行的结果返回给函数f.实参是具有实际意义,是一个实际的值。g.形参不具有实际意义,其值在函数调用时再传入,传递参数时形参与实参一一对应(推荐)。h.函数没有对应实参时,默认返回值为undefined。i.arguments访问的是实际参数,对实参或arguments的修改都会同步反映到两者身上,但能arguments访问的前提是实参必须先被定义
// 函数名加括号()时,表示调用函数,未加()时,表示函数本身。function a() { n = n + 1;}var y = a; // 表示将函数a赋值给变量y,函数并不进行调用运行console.log(y); 输出函数var y = a(); // 表示调用运行a函数,并把a函数的结果赋值给yconsole.log(y); 因函数没有返回值,默认返回值undefined,故输出undefined
// 函数的调用/执行:函数名(实参);function sum() { var a = 10; var b = 20; // console.log(a + b); // 函数返回值 return a + b;}console.log(sum());// 函数的调用/执行:函数名(形参);function sum(first, second) { return first + second;}console.log(sum(20, 40));
// 使用 return 语句时,函数会停止执行,并返回指定的值function outer(num) { num++; console.log(num); return function() { num++; console.log(num); } num++; // 不执行 console.log(num); // 不执行}var result1 = outer(0); // 输出1result1(); // 输出2result1(); // 输出3var result2 = outer(1); // 输出2result2(); // 输出3result2(); // 输出4
// 匿名函数// 可用来解决命名冲突var year = 2016;(function() { var year = 2015; console.log(year);})();console.log(year)
// 非匿名函数也可以解决命名冲突var year = 2016;function show() { var year = 2015; console.log(year);} show();console.log(year)
6.作用域
a.作用域分类 1)全局作用域:在window下属于全局作用域 2)局部作用域:每个函数,均会创建一个局部作用域b.不同作用域的访问关系: 函数外部不能访问函数外部 var year = 2016; function show() { var year = 2015; console.log(year); } show(); console.log(year) 输出: 2015 2016
7.编译
a.预编译期:进行空间的创建(var和function才会创建空间)b.执行期:用于空间的赋值,顺序从上到下c.多个作用域形成作用域链 在局部作用域当中出现变量的时候,首先查找当前的作用域是否具有存储空间(开辟空间)。 如果有则直接采用,如果没有则需要向父级进行查找,如果父级没有则继续往上查找,知道找到window下为止。 如果window下也不存在该存储空间,会在全局作用域下进行空间的创建。而这种作用域层层的关系,成为作用域链。d.函数的编译执行规则1)同名的函数所创建的空间即函数本身会发生覆盖,后创建的函数覆盖之前的函数2)若是匿名函数被调用多次,其所开辟的空间互相之间相互独立,相互之间不影响
(function() { var a = 1; function inner() { a += 1; console.log(a); }inner(); })(); // 输出2 (function() { var a = 1; function inner() { a += 1; console.log(a); }inner(); })(); // 输出2 (function() { var a = 1; function inner() { a += 1; console.log(a); }inner(); })(); // 输出2
3)同一个函数被赋值给不同变量时,各变量所代表的都是单独的函数,各自之间开辟的空间互相不受影响 匿名函数也具有相同性质,一旦被赋值给某个变量,在被调用时,就会在该变量下开辟固定的空间来存放变量。
function outer() { var a = 1; return function inner() { a += 1; console.log(a); } } var f1 = outer(); f1(); // 输出2 f1(); // 输出3 var f2 = outer(); f2(); // 输出2 f2(); // 输出3 function outer() { var a = 1; return function() { a += 1; console.log(a); } } var f1 = outer(); f1(); // 输出2 f1(); // 输出3 var f2 = outer(); f2(); // 输出2 f2(); // 输出3 var f1 = (function() { var a = 1; return function() { a += 1; console.log(a); } })(); f1(); // 输出2 f1(); // 输出3 var f2 = (function() { var a = 1; return function() { a += 1; console.log(a); } })(); f2(); // 输出2 f2(); // 输出3
4)若函数的形参名和内部定义的变量名相同时,在定义的变量没有被赋值之前,该变量的值由形参传入,赋值之后,改为被赋值的新值。
// 例子 var a = 100; function show (a) { console.log(a); a++; console.log(a); var a = 10; console.log(a); var a = a++ + 20; console.log(a); a = ++a + 20; console.log(a); }show(600) 600 601 10 30 51 // 例子变化 var a = 100; function show (a) { console.log(a); a++; console.log(a); var a = 10; console.log(a); a = a++; console.log(a); var a = a + a++ + a + 20; console.log(a); a = ++a + 20; console.log(a); }show(600); console.log(a); 600 601 10 10 51 72 100
5)全局变量只有赋值语句才可以定义,包括连续赋值的语句。 单独用一个a;的语句是无法定义出undefined的全局变量的,此时浏览器会报错。 因为只有赋值语句才会触发向上查找该变量的存储空间,若未查找到,才会开辟空间,而a;语句没有赋值,所以不会触发查找。
function outer() { function inner() { a; console.log(a); }inner(); }outer(); // 报错 (function() { var a = b = 5; // b变量被赋值语句定义为全局变量 console.log(a); // 输出5 console.log(typeof(a)); // 输出number console.log(b); // 输出5 console.log(typeof(b)); // 输出number })(); // console.log(a); // 无法输出a,因a是函数中的变量,在全局中未定义,输出则会报错 console.log(typeof(a)); // 输出undefined console.log(b); // 输出5 console.log(typeof(b)); // 输出number
6)全局变量的调用语句只有在全局变量定义的语句之后才有效,如果在定义语句之前,则会报错。 因为变量在被赋值的时候才开始向上查找该变量的值,若未在父级查找到,才会在全局作用域上开辟空间。 在赋值语句运行之前是不会开辟空间的,所以变量在被调用时,无法查找到空间,即会报错
function outer() { console.log(a); function inner() { a = "内容"; console.log(a); }inner(); }outer(); // 报错,a未定义
7)对于同一变量名,同时存在局部变量和全局变量,或者局部变量和父函数的局部变量时。 无论调用局部变量是在定义之前还是之后,都只会查找局部变量。
function outer() { a = "内容1"; function inner() { console.log(a); var a = "内容2"; console.log(a); }inner(); }outer(); console.log(a); // 输出undefined 内容2 内容1
8)预编译期创建空间时,不会对变量进行赋值操作,此时变量的值为undefined,赋值是在函数被调用执行的时候才会进行。如果调用函数时,函数内部在定义变量的语句之前调用变量,则此变量的值为undefined。
function outer() { var a = "内容1"; function inner() { console.log(a); var a = "内容2"; console.log(a); }inner(); }outer(); // 输出undefined 内容2
9)在定义变量之前的语句调用该变量时,变量的值虽然是undefined,但也是可以参与运算,只是将undefined的值当做一个字符串参与计算。
var a = "HTML5"; b = "你好"; Test(); function Test() { console.log(a + " " + b); var a = "welcome"; var b = "h5"; console.log(a + " " + b); } console.log(a + " " + b); // 输出undefined undefined // 输出welcome h5 // 输出HTML5 你好
10)函数如果在其内部调用外部函数时,外部函数所开辟的空间,即外部函数内部的变量,与调用的函数空间无关,只与外部函数的空间相关。 即两个单独开辟空间的函数,无论如何调用,都不影响它们的空间之间的关系。 函数的空间值在预编译期被开辟,与执行期(调用的过程)无关。
var name = "a"; function first() { alert(name); } function second() { var name = "b"; first(); } second(); // 输出a
11)函数如果调用其内部函数或兄弟函数中的变量时,会因查找不到该变量而认为该变量为未定义,造成报错
function outer() { var a = 2; }outer(); function show() { var b = 0; b += a; function inner() { var a = 1; }inner(); console.log(b); }show(); // 报错a未定义
六、调试
1.调试方法分类
a.注释方式b.弹窗命令c.控制台d.文档命令
2.调试方法详解
a.注释方式 1)单行注释 // 空格书写注释内容 // alert("JS test"); 单行注释不可换行 2)多行注释(块注释)(函数功能的注释) 注释规范: 多行注释可以换行
<script type="text/javascript"> /* * [sum 求和的功能] * @param {[数字]} a [第一个数字] * @param {[数字]} b [第二个数字] * @return {[数字]} [求和的结果] * sum(1, 100) 使用范例 * 作者:陈立 * 时间:2015.12.30 */ function sum(a, b) { return a + b; } </script>使用范围:
针对文件/函数的功能以及用法进行描述的时候用块注释,其他情况下一般使用单行注释。b.弹窗命令 弹窗命令种类:alert、confirm、prompt alert("警告弹窗"); confirm("确认弹窗"); prompt("对话弹窗");
<script type="text/javascript"> alert("警告弹窗"); confirm("确认弹窗"); prompt("对话弹窗"); </script>
注意:此方法不常用。c.控制台调试 1) 谷歌控制台 a)查看谷歌控制台(console)的提示信息 b)控制台输出命令
<script type="text/javascript"> console.log("你好"); </script>
注意:此方法常用 c)测试JavaScript代码的执行时间,timeName需要保持 兼容:IE8+支持 命令: console.time(timeName); console.timeEnd(timeEnd); 例子:
console.time('test'); for (var i = 0; i < 100; i++) { for ( var j = 0; j < 100; j++) { console.log(i * j); } } console.timeEnd('test');
2)firebug 3)IE Developer Toolsd.文档命令 document.write(); document.writeln();例子: document.write("<p>啊啊</p>"); document.writeln("哦哦"); document.writeln("哦哦<br />"); document.writeln("<pre>啦啦</pre>"); // pre元素可以定义预格式的文本(原样输出) 含义:document是文档对象,write是方法/功能 对象:方法的调试调用write功能 区别:write与writeln方法类似,只是writeln每个表达式之后会多写一个换行符号(\n属于转义字符,含义就是换行。 但需要用<pre></pre>才会运行\n)。 注意:面试要能写,因会在网页中显示内容,影响排版,故不常用。e.使用高级计时器计算代码运行时间
,
// 计算代码运行时间方法
var time1 = new Date();
// 需要计算运行时间的代码
var time2 = new Date();
var difference = time1.getTime() - time2.getTime();
console.log(difference);
0 0
- HTML5学习笔记 —— JavaScript开发入门
- HTML5学习笔记 —— HTML开发入门
- HTML5学习笔记 —— CSS开发入门
- HTML5学习笔记 —— SEO入门
- HTML5学习笔记 —— JavaScript基础知识
- HTML5学习笔记 —— JavaScript语句
- HTML5学习笔记 —— JavaScript基础知识
- HTML5学习笔记 —— 表格、表单入门
- JavaScript学习笔记——慕课网(JavaScript入门篇)
- HTML5混编学习笔记:HTML5入门
- HTML5学习笔记 —— 移动端开发要点
- NDK开发学习笔记—JNI入门
- JavaScript入门学习笔记
- javaScript学习笔记---入门
- JavaScript入门学习笔记
- 《HTML5学习笔记—基础知识》
- Javascript学习笔记12——Ajax入门
- Javascript学习笔记十二——Ajax入门
- Ubuntu Fluxbox GUI with x11vnc and Xvfb
- iOS 退出登录
- 661.Convert BST to Greater Tree
- Celery定时任务
- excel字段过多,导入数据库 存在截断问题的解决方法
- HTML5学习笔记 —— JavaScript开发入门
- lua脚本语言学习
- 前端框架Vue(10)——vuex 状态管理
- 陶陶摘苹果
- weasis调节窗位相关代码分析
- Zstack之RSSI信号值获取以及显示
- 使用HttpClient4,post提交multipart/form-data数据
- HashTable深入理解
- centos tftp配置