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
原创粉丝点击