• JS高级语法与JS选择器


    元素(element)和节点(node)

    childNode属性和children属性的区别

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
     <div id="parentDiv">
         <!--注释-->
         <div></div>
     </div>
     <script>
         console.log(document.getElementById('parentDiv').childNodes); //NodeList[5]
         console.log(document.getElementById('parentDiv').children) ;  //HTMLCollection[1]
     </script>
    </body>
    </html>

    childNodes属性返回的是NodeList数组,是属于节点(也包括元素)的属性,而children属性返回的是子元素,是属于元素的属性

    而在Nodelist数组里面也有元素存在,证明了元素也是节点的一种,即元素节点。

    W3C中的解释是:

    在 HTML DOM (文档对象模型)中,每个部分都是节点
    
    文档本身是文档节点
    所有 HTML 元素是元素节点
    所有 HTML 属性是属性节点
    HTML 元素内的文本是文本节点 (包括回车符,空格,空白字符也是属于文本节点)
    注释是注释节点

    Element 对象可以拥有类型为元素节点、文本节点、注释节点的子节点。

    NodeList 对象表示节点列表,比如 HTML 元素的子节点集合。

    元素也可以拥有属性。属性是属性节点。
    总结:元素是元素节点,是节点中的一种,但元素节点中可以包含很多的节点

    nodeName(纯大写) 属性含有某个节点的名称

    元素节点的nodeName 是标签名称
    属性节点的nodeName 是属性名称
    文本节点的nodeName 永远是 #text
    文档节点的nodeName 永远是 #document
    
    nodeValue 对于文本节点,nodeValue 属性包含文本。 对于属性节点,nodeValue 属性包含属性值
    nodeValue 属性对于文档节点和元素节点是不可用的 

    nodeType 属性可返回节点的类型

    Element 元素     1
    Attribute 属性   2
    Text 文本        3
    CDATA Section CDATA断     4
    Entity Reference 实体参数  5
    Entity 实体       6
    Processing Instrucion 处理指令  7
    Comment 注释    8
    Document 文档    9
    Document Type 文档类型   10
    Document Fragment 文档片断   11

    添加和删除节点(HTML 元素)

    创建新的 HTML 元素

    如需向 HTML DOM 添加新元素,您必须首先创建该元素(元素节点),然后向一个已存在的元素追加该元素

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="div1">
        <p id="p1">这是一个段落</p>
        <p id="p2">这是另一个段落</p>
    </div>
    
    </body>
    <script>
    var para=document.createElement("p");
    
    var node=document.createTextNode("这是新段落。");
    para.appendChild(node);
    
    var element=document.getElementById("div1");
    element.appendChild(para);
    </script>
    </html>
    
    <!-- 为这段代码创建新的 <p> 元素:
    var para=document.createElement("p");
    此时检查页面可以看到div里面已经生成了<p>元素
    
    如需向 <p> 元素添加文本,您必须首先创建文本节点。
    这段代码创建了一个文本节点:
    var node=document.createTextNode("这是新段落。");
    然后您必须向 <p> 元素追加这个文本节点:
    para.appendChild(node);
    最后您必须向一个已有的元素追加这个新元素。
    这段代码找到一个已有的元素:
    var element=document.getElementById("div1");
    这段代码向这个已有的元素追加新元素:
    element.appendChild(para); -->

    删除已有的 HTML 元素

    如需删除 HTML 元素,您必须首先获得该元素的父元素

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <div id="div1">
    <p id="p1">这是一个段落。</p>
    <p id="p2">这是另一个段落。</p>
    </div>
     
    </body>
    <script>
    var parent=document.getElementById("div1");
    
    var child=document.getElementById("p1");
    
    parent.removeChild(child);
    </script>
    </html>
    
    <!-- 例子解释:
    这个 HTML 文档含有拥有两个子节点(两个 <p> 元素)的 <div> 元素:
    <div id="div1">
    <p id="p1">这是一个段落。</p>
    <p id="p2">这是另一个段落。</p>
    </div>
    
    找到 id="div1" 的元素:
    var parent=document.getElementById("div1");
    找到 id="p1" 的 <p> 元素:
    var child=document.getElementById("p1");
    
    从父元素中删除子元素:
    parent.removeChild(child);
    
    提示:如果能够在不引用父元素的情况下删除某个元素,就太好了。
    不过很遗憾。DOM 需要清楚您需要删除的元素,以及它的父元素。
    这是常用的解决方案:
    找到您希望删除的子元素,然后使用其 parentNode 属性来找到父元素:
    var child=document.getElementById("p1");
    child.parentNode.removeChild(child); -->

    常用节点操作

    1.节点查找
    document.getElementById,document.getElementByTagName,document.getElementByName ,document.getElementByClassName
    document.querySelector() 参数为选择器
    document.forms 选取页面中的所有表单元素
    2.增加节点
    增加节点前必须先使用document.createElement()创建元素节点,参数为标签名
    m.appendChild(n) 为m元素在末尾添加n节点
    m.insertBefore(k,n) 在m元素的k节点前添加n节点
    3.删除节点
    m.removeChild(n)删除m元素中的n节点
    m.replaceChild(k,n)用n节点取代m元素中的k节点
    4.复制节点
    m.cloneChild() 复制m节点,并将复制出来的节点作为返回值
    参数为true时,则将m元素的后代元素也一并复制。否则,仅复制m元素本身
    
    
    节点属性操作
    
    节点(自身)属性:
      
    attributes - 节点(元素)的 属性节点
    nodeType – 节点类型
    nodeValue – 节点值
    nodeName – 节点名称
    innerHTML - 节点(元素)的文本值
    
    1.节点属性值选取
    m.属性名  (:驼峰形式 )     m.className
    m[“属性名”]      m.['className']
    
    m.getAttribute(“属性名”)  :加引号,html的形式       m.getAttribute("class")
    
    2.节点属性修改
    前两种选取方法时,直接赋值即可
    m.setAttribute("属性名",“值”)
    
    
    3.创建属性节点并设置属性值
    var info_node=document.createAttribute("info");//创建
    info_node.value='123';//设置
    sup1.setAttributeNode(info_node);//添加
    
    4.复制节点
    var body = document.querySelector('body');
    true深拷贝,拷贝自身与内容, false浅拷贝,只拷贝自身标签
    var cl_body = body.cloneNode(true);
    console.log(cl_body);
    
    
     
    JS DOM节点(当前标签和同级、父级、子级..之间的关系)
    1. 通过顶层document节点获取
        1) document.getElementById(elementId) //根据id获得
        2) document.getElementsByName(elementName) //根据name获得
        3) document.getElementsByTagName(tagName) //根据标签名获得
    2、通过父节点获取
        1) parentObj.firstChild //获得第一个子节点
        2) parentObj.lastChild //获得第二个子节点
        3) parentObj.childNodes //获取作为指定对象直接后代的HTML元素和TextNode对象的集合
        4) parentObj.children //非标准dom集合,建议使用childNodes
        5) parentObj.getElementsByTagName(tagName) //获得该标签下标签名为tagName的所有标签
    3、通过临近节点获取
        1) neighbourNode.previousSibling //获得同级前一个标签
        2) neighbourNode.nextSibling //获得同级后一个标签
    4、通过子节点获取
        1) childNode.parentNode //获得父标签

    事件

    onload:页面加载完毕事件,只附属于window对象
    onclick:鼠标点击时间
    onmouseover:鼠标悬浮事件
    onmouseout:鼠标移开事件

    on事件绑定方式

    document.onclick = function() {
    console.log("文档点击");
    }

    on事件只能绑定一个方法,重复绑定保留最后一次绑定的方法

    document.onclick = function() {
    console.log("文档点击");
    }

    事件的移除

    document.onclick = null;

    非on事件绑定方式

    document.addEventListener('click', function() {
    console.log("点击1");
    })
    document.addEventListener('click', function() { console.log("点击2"); })

    非on事件可以同时绑定多个方法,被绑定的方法依次被执行
    addEventListener第三个参数(true|false)决定冒泡的方式

    function fn () {}
    document.addEventListener('click', fn);

    事件的移除
    document.removeEventListener('click', fn,false);

    事件的三种绑定方式的思考

    方法一:嵌入dom
    把onclick绑定在标签上
    HTML元素行间事件(也可以叫HTMl事件处理程序),直接在html标签里添加事件。
    缺点:html和js代码紧密耦合
    <input id="btn1" type="button" onclick="test();" />
     
    方法二:直接绑定
    onclick的js绑定办法
    
    //把一个函数赋值给一个事件处理程序属性。(这种方式也叫做Dom0级事件处理程序)
    var btn1 = document.getElementById('btn1');
    function abc() {
        alert('abc');
    }
    btn1.onclick = abc; //当点击的时候执行abc这个函数,等价于 btn1.onclick=function abc(){alert('abc');}
    //btn1.onclick = null; //去掉绑定的事件
    
    方法三:事件监听
    
     click的js绑定办法(js的话推荐这种)
    //通过“事件监听”的方式来绑定事件(也叫Dom2级事件处理程序)
    
    var btn2 = document.getElementById('btn2');
    btn2.addEventListener('click', showMsg, false); //鼠标单击的时候调用showMes这个函数  
    function showMsg() {
        alert("事件监听");
    }
    //btn2.removeEventListener('click', showMsg, false); //去除绑定
    
    
    方法一
    最原始的写法:和html混合在一起写,缺点是代码高冗余,且无法添加多个事件处理函数如上文对事件的举例则为典型的**html事件处理程序*写法
    
    方法二
    dom0级:将html代码和js代码分离,且支持匿名函数,可以看到完美的改进了1的冗余缺憾,所有的事件相关操作都在js中完成
    
    方法三
    dom2级:ie使用attachEventListener其他非ie使用addEventListener,可以支持绑定多个事件,瞧吧,又一个缺憾被完美解决了~,而且dom2级还可以自定义事件流,下一篇会分析事件流模型
    
    dom3级:对事件进行了更广而全的分类,请自行查阅

    实例运用一

    </head>
    <body>
        <div class="div"></div>
        <div class="div"></div>
    </body>
    <script>
        // js事件: 页面标签在满足某种条件下可以完成指定功能的这种过程, 成之为事件
        // 某种条件: 如鼠标点击标签: 点击事件 | 鼠标双击标签: 双击事件 | 键盘按下: 键盘按下事件
        // 指定功能: 就是开发者根据实际需求完整相应的功能实现
    
        // 钩子函数: 就是满足某种条件被系统回调的函数(完成指定功能)
    
        // 点击事件: 明确激活钩子的条件 = 激活钩子后改处理什么逻辑, 完成指定功能(函数)
        var div = document.querySelector(".div");  // 找到的是第一个.div
        div.onclick = function () {
            // alert(123)
            this.style.backgroundColor = "pink";
        }
    
        // 明确第一个及第二个
        var divs = document.querySelectorAll('.div');
        divs[1].ondblclick = function () {
            divs[0].style.backgroundColor = "yellow";
        }
    
    </script>
    </html>

    实例运用二

    复习并延伸
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>复习预习</title>
        <style>
            [key='value'] {
                color: #0f8209;
            }
        </style>
    </head>
    <body>
        <div class="ele" alert="OK">div div div</div>
    </body>
    <script>
        // 1.面向对象js
        // ES5
        // 普通的单一对象
        var obj = {
            // 普通对象的属性
            key: "value",
            fn: function () {
                console.log("普通对象的方法")
            }
        };
        console.log(obj.key);
        console.log(obj["key"]);
        // 1.key的类型为字符串类型
        // 结论:
        //      js支持的标识符可以省略引号, 反之不可以省略
        //      不支持的标识符访问方式: 不可以采用.语法,需要采用[]语法,eg:obj["background-color"]
    
        var obj1 = {
            "name": "obj1",
            // key有时候会出现js不能直接支持的标识符书写方式
            // 需求: obj1用来描述页面标签的各种颜色
            color: "red",
            // "color": "red",
            "background-color": "yellow"
        }
        console.log(obj1.name);
        console.log(obj1["name"]);
        console.log(obj1.color);
        // obj1.background = 12;
        // color = 10;
        console.log(obj1["background-color"]);
    
        // 2. 对象可以任意添加或删除属性
        var obj2 = {
            name: "obj2"
        };
        console.log(obj2);
        // 删除属性
        delete obj2.name;
        console.log(obj2);
        // 添加属性
        obj2.age = 8;
        console.log(obj2);
    
        // 拓展: 获取的页面元素就是标签对象, 可以对其添加任意属性
        var ele = document.querySelector('.ele');
        console.log(ele.info);  // 直接使用无值, 原因ele并没有添加该属性
        ele.info = "添加的属性信息";  // 添加属性
        console.log(ele.info);  // 添加属性后就可以正常方式添加的属性值
        delete ele.info;  // 删除操作
        console.log(ele.info);  // 删除后属性又会消失
    
        // 构造函数
        function Perple(name, age) {
            this.name = name;
            this.age = age;
            this.fn = function () {
                console.log("fn")
            }
        }
        // 实例化对象
        var p = new Perple("张三", 18);
        p.fn();
    
        // ES6
        class Student {
            constructor (name, age) {
                this.name = name;
                this.age = age;
            }
            fn () {
                console.log("fn")
            }
        }
        var s = new Student("张三", 18);
        s.fn();
    
    </script>
    <script>
        // getElementById只能由document调用
        var ele = document.getElementsByClassName("ele")[0];
        console.log(ele);
        ele = document.querySelector(".ele");
        console.log(ele);
        ele = document.querySelectorAll(".ele")[0];
        console.log(ele);
    
        // 该添加属性的方式只映射到js代码中
        ele.index = 123;
        console.log(ele.index);
    
        // js如何操作元素(页面标签)的全局属性, 映射到html代码中
        ele = document.querySelector('[alert]');  // 通过全局属性获取元素
        console.log(ele);
        // 获取全局属性值
        var info = ele.getAttribute('alert');
        console.log(info);
        // 修改全局属性值
        ele.setAttribute('alert', 'no ok');
        // 添加全局属性值(映射到html代码中) => 结合CSS来控制页面标签的样式
        ele.setAttribute('key', 'value');
    
    </script>
    </html>

    事件参数event

    存放事件信息的回调参数

    在触发DOM上某个事件时,会产生一个事件对象event,这个对象包含着所有事件有关的信息(导致事件的元素、事件的类型、与特定事件相关的信息)
    所有浏览器都支持Event对象,但支持方式不同
    IE中的事件对象:window.event

    阻止事件冒泡 
    
    DOM中提供stopPropagation()方法,但IE不支持,使用event对象在事件函数中调用就行
    IE中提供的是,cancelBubble属性,默认为false,当它设置为true时,就是阻止事件冒泡,也是用event对象在事件函数中调用 
     
    jQuery中提供了stopPropagation()方法来停止事件冒泡,当需要时,只需用用event对象来调用就行,即event.stopPropagation();
    
    默认行为
    
    阻止默认行为 
    DOM中提供preventDefault()方法来取消事件默认行为,但是只有当cancelable属性设置为true的事件,才可以使用preventDefault()来取消事件默认行为,使用event对象在事件函数中调用就行
    IE中提供的是returnValue属性,默认为true,当它设置为false时,就是取消事件默认行为,也是用event对象在事件函数中调用
    jQuery中提供了preventDefault()方法来阻止元素的默认行为,只需要用event对象来调用就好,即event.preventDefault()
    如果想同时对事件对象停止冒泡和默认行为,可以在事件处理函数中返回false。这是对事件对象同时调用stopPropagation()方法和preventDefault()方法的一种简写方式 

    事件注意点

    1、event代表事件的状态,例如触发event对象的元素、鼠标的位置及状态、按下的键等等;
    2、event对象只在事件发生的过程中才有效。
    firefox里的event跟IE里的不同,IE里的是全局变量,随时可用;
    firefox里的要用参数引导才能用,是运行时的临时变量
    
    在IE/Opera中是window.event,在Firefox中是event;
    而事件的对象,在IE中是window.event.srcElement,在Firefox中是event.target,Opera中两者都可用

    处理冒泡与默认事件

    事件的冒泡:父子都具有点击事件,不处理的话,点击子级也会出发父级的点击事件

    如果提供了事件对象,则这是一个非IE浏览器
    if ( e && e.stopPropagation )
    因此它支持W3C的stopPropagation()方法
    e.stopPropagation(); 
    else
    否则,我们需要使用IE的方式来取消事件冒泡 
    window.event.cancelBubble = true;
    return false;

    处理冒泡实例

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>事件对象</title>
        <style>
            body {
                margin: 0;
            }
            .box {
                background-color: pink;
            }
            .sup {
                 200px;
                height: 200px;
                background-color: red;
            }
            .sub {
                 100px;
                height: 100px;
                background-color: orange;
            }
        </style>
    </head>
    <body>
        <div class="box">12345</div>
    
        <div class="sup">
            <div class="sub"></div>
        </div>
    
        <a href="https://www.baidu.com">只想相应点击事件</a>
    </body>
    <script>
        var box = document.querySelector('.box');
        // 事件的钩子函数, 系统回调时传递了一个值, 该值为事件对象
        box.onclick = function (ev) {  // 回调函数
            console.log(ev)
            // 特殊按键 altKey | shiftKey | ctrlKey
            console.log(ev.altKey)
            // 鼠标的点击点
            console.log(ev.clientX, ev.clientY)
        }
    </script>
    <script>
        var sup = document.querySelector('.sup');
        var sub = document.querySelector('.sub');
    
        // 事件默认有冒泡, 子级相应事件后,会将事件传递给父级,如果父级有相同事件,也会被激活, 最终传递给document
        sub.onclick = function (ev) {
            console.log(ev);
            // 取消冒泡, 当自身处理事件后, 该事件就处理完毕, 结束, 不再向上传递
            ev.cancelBubble = true;
            console.log("子级被点击了")
        };
        sup.onclick = function () {
            console.log("父级被点击了")
        };
        document.onclick = function () {
            console.log("文档被点击了")
        }
    </script>
    </html>

    事件默认行为:当一个事件发生时浏览器自己会做的事情

    如果提供了事件对象,则这是一个非IE浏览器 
    if ( e && e.preventDefault ) 
    阻止默认浏览器动作(W3C) 
    e.preventDefault(); 
    else
    IE中阻止函数器默认动作的方式 
    window.event.returnValue = false; 
    return false;
    
    既然return false 和 e.preventDefault()都是一样的效果,那它们有区别吗?当然有
    仅仅是在HTML事件属性 和 DOM0级事件处理方法中 才能通过返回 return false 的形式组织事件宿主的默认行为

    处理默认事件实例

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>事件对象</title>
        <style>
            body {
                margin: 0;
            }
            .box {
                background-color: pink;
            }
            .sup {
                 200px;
                height: 200px;
                background-color: red;
            }
            .sub {
                 100px;
                height: 100px;
                background-color: orange;
            }
        </style>
    </head>
    <body>
        <div class="box">12345</div>
    
        <div class="sup">
            <div class="sub"></div>
        </div>
    
        <a href="https://www.baidu.com">只想相应点击事件</a>
    </body>
    <script>
        var box = document.querySelector('.box');
        // 事件的钩子函数, 系统回调时传递了一个值, 该值为事件对象
        box.onclick = function (ev) {  // 回调函数
            console.log(ev)
            // 特殊按键 altKey | shiftKey | ctrlKey
            console.log(ev.altKey)
            // 鼠标的点击点
            console.log(ev.clientX, ev.clientY)
        }
    </script>
    <script>
        // 默认事件
        var aBtn = document.querySelector('a');
        aBtn.onclick = function (ev) {
            ev.cancelBubble = true;
            console.log("a被点击了");
            // 手动转跳页面
            open('https://www.oldboyedu.com', '_self');
            // a标签默认会完成转跳, 如果取消默认事件
            return false;
        }
    
    </script>
    </html>

    再补充一些

    默认操作 具体指的是什么呢?
    (1)把单击事件处理程序注册到一个锚元素,而不是一个外层的<div>上,那么就要面对另外一个问题:当用户单击链接时,浏览器会加载一个新页面。

    (2)当用户在编辑完表单后按下回车键时,会触发表单的submit事件,在此事件发生后,表单提交才会真正发生。
    这种行为与我们讨论的事件处理程序不是同一个概念,它是单击标签元素的默认操作。

    如果我们不希望执行这种默认操作,那么在事件对象上调用.stopPropagation()方法也无济于事,因为默认操作不是在正常的事件传播流中发生的
    在这种情况下,处理方法有:

    1、w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false;
    preventDefault它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。既然是说默认行为,当然是元素必须有默认行为才能被取消,如果元素本身就没有默认行为,调用当然就无效了。什么元素有默认行为呢?如链接<a>,提交按钮<input type=”submit”>等。当Event 对象的 cancelable为false时,表示没有默认行为,这时即使有默认行为,调用preventDefault也是不会起作用的。
    1 <a href="http://www.cnblogs.com/yycode/" id="testA" >caibaojian.com</a>
    
    var a = document.getElementById("testA");
    a.onclick =function(e){
        if(e.preventDefault){
            e.preventDefault();//
        }else{
            window.event.returnValue = false;//IE
         //注意:这个地方是无法用return false代替的 
         //return false只能取消元素
        }
    }
    
    
    2、return false;
    javascript的return false只会阻止默认行为,而是用jQuery的话则既阻止默认行为又防止对象冒泡

    常见事件

    鼠标事件

    var box = document.querySelector('.box');
    
    1. 点击事件
    box.onclick = function () {
        console.log("单击");
    };
    2. 双击事件(应用场景不广)
    box.ondblclick = function () {
        console.log("双击");
    };
    3. 鼠标右键
    box.oncontextmenu = function () {
        console.log("右键了");
        return false;
    };
    4. 鼠标悬浮 | 移动 | 按下 | 抬起 | 离开
    box.onmouseover = function () {
        console.log("悬浮");
    };
    box.onmousemove = function () {
        console.log("移动");
    };
    box.onmousedown = function () {
        console.log("按下");
    };
    box.onmouseup = function () {
        console.log("抬起");
    };
    box.onmouseout = function () {
        console.log("离开");
    }
    
    事件参数ev
    ev.clientX:点击点X坐标
    ev.clientY:点击点Y坐标

    over | out   VS   enter | leave

    总结:
    1. 将子级与父级分开考虑, 大家都有各自的悬浮离开事件, 采用 over | out 组合
    2. 将子级纳入父级考虑范围, 也就是只有父级去相应悬浮离开事件, 采用 enter | leave 组合
    3. 单独考虑一个盒子的悬浮离开事件, 两套均可以
    
    特性
    从父级移至子级, 会触发out事件, 紧接着触发子级的over事件, 并可以冒泡给父级
    
    从父级移至子级, leave事件并不会触发, 它认为子级是属于父级的一部分, enter事件, 也不会再次触发
    
    悬浮子级:
    sub over => sup over  支持冒泡
    sup enter => sub enter  不支持冒泡

    键盘事件

    键盘事件
    onkeydown:键盘按下会触发,长按持续触发
    onkeyup:键盘抬起
    
    事件参数ev
    
    ev.keyCode:按键编号
    ev.altKey:alt特殊按键
    ev.ctrlKey:ctrl特殊按键
    ev.shiftKey:shift特殊按键
    
    
    <head>
        <meta charset="UTF-8">
        <title>键盘事件</title>
        <style>
            .box {
                 100px;
                height: 100px;
                background: orange;
                position: absolute;
                top: 0;
                left: 0;
            }
        </style>
    </head>
    <body>
        <div class="box"></div>
    </body>
    <script>
        // 键盘长按会一直触发按下事件
        document.onkeydown = function (ev) {
            console.log(ev);
            // 按下的键盘编号
            console.log("按下", ev.keyCode);
            // console.log(ev.which);
        }
        document.onkeyup = function (ev) {
            console.log("抬起", ev.keyCode);
        }
    
        // 左上右下: 37-40
        var box = document.querySelector('.box');
        document.onkeydown = function (ev) {
            switch (ev.keyCode) {
                case 37:
                    box.style.left = box.offsetLeft - 10 + 'px';
                    break;
                case 38:
                    box.style.top = box.offsetTop - 10 + 'px';
                    break;
                case 39:
                    box.style.left = box.offsetLeft + 10 + 'px';
                    break;
                case 40:
                    box.style.top = box.offsetTop + 10 + 'px';
                    break;
            }
        }
    </script>
    </html>

    表单事件

    onfocus:获取焦点
    onblur:失去焦点
    onselect:文本被选中
    oninput:值改变
    onchange:值改变,且需要在失去焦点后才能触发
    onsubmit:表单默认提交事件

    文档事件

    文档事件由window调用
    onload:页面加载完毕触发
    onbeforeunload:页面退出或刷新警告,需要设置回调函数返回值,返回值随意

    图片事件 

    onerror:图片加载失败

    页面事件

    onscroll:页面滚动
    onresize:页面尺寸调整
    window.scrollY:页面下滚距离

    文档页面事件运用实例

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>其他事件</title>
        <script>
            // 当页面加载完毕之后再回调
            window.onload = function () {
                var box = document.querySelector('.box');
                console.log(box);
            }
    
            // 页面滚动可以设置给 window | document
            var isShow = false;
            window.onscroll = function () {
                console.log(window.scrollY);
                if (window.scrollY >= 1200) {
                    if (!isShow) {
                        console.log("将返回Top按钮显示");
                        isShow = true;
                    }
                } else  {
                    if (isShow) {
                        isShow = false;
                    }
                }
            }
        </script>
    </head>
    <body>
        <div class="box"></div>
        <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
    </body>
    
    </html>

    JS选择器

    getElement系列

    通过id名获取唯一满足条件的页面元素

    document.getElementById('id名');
    该方法只能由document调用
    任何HTML元素可以有一个id属性,在文档中该值必须唯一
    若浏览器中出现多个id名的情况,CSS样式对所有该id名的元素都生效,但javascript脚本仅对第一个出现该id名的元素生效。
    getElementById()该方法接收一个参数:要取得元素的id,若找到则返回该元素,若不存在则返回null
    注意:document.getElementById方法的内部实现需要用到this,这个this本来被期望指向document
    
    跨浏览器兼容
    1:在ie7中,使用getElementById()的时候,接收的参数id不区分大小写。
    2:在表单元素中,如果表单设置有name属性,其name属性会被当做id识别出来。
    3:id是唯一的,但name属性并不是唯一的。具有该名称的隐式全局变量会引用一个类数组对象,包括所有该命名的元素

    通过class名获取所有满足条件的页面元素

    document.getElementsByClassName('class名');
    该方法可以由document及任意页面元素对象调用
    document.getElementsByClass("class1
    class2")可以拿到同时拥有class1和class2的元素,中间用空格隔开,不区分class1和class2的顺序。
    
    兼容性:IE8及其以下版本的浏览器未实现getElementsByClassName方法
    返回值为HTMLCollection (一个类数组结果的对象,使用方式同数组)
    没有匹配到任何结果返回空HTMLCollection对象 ([]) 

    通过name属性获取元素

    getElementsByName(返回值是一个nodeList集合(区别于Array),可作用于Dom元素)
    getElementsByName()方法接收一个参数,即要取得元素的name值。
    
    document.getElementsByName("Name");Name为要获取元素的name属性值,这个方法一般适用于提交表单数据,当
    元素为form、img、iframe、applet、embed、object的时候设置name属性时,会自动在Document对象中创建以该
    name属性值命名的属性。
    所以可以通过document.domName引用相应的dom对象。
    
    在ie9中,getElementsByName()只对表单元素起作用。
    IE9-浏览器中使用getElementsByName()方法也会返回id属性匹配的元素。因此,不要将name和id属性设置为相同的值。

    通过tag名获取所有满足条件的页面元素

    document.getElementsByTagName('tag名');
    该方法可以由document及任意页面元素对象调用
    返回值为HTMLCollection (一个类数组结果的对象,使用方式同数组)
    没有匹配到任何结果返回空HTMLCollection对象 ([]) 
    可以使用方括号语法或item()方法来访问类数组对象中的项,length属性表示对象中元素的数量。
    [注意]通过getElementsByTagName()方法取得的类数组对象有一个namedItem()方法,可以通过元素的name属性取得集合中的第一个值。safari和IE不支持该方法。document.getElementsByTagName("*")表示匹配文档的所有元素

    querySelect系列

    获取第一个匹配到的页面元素

    document.querySelector('css语法选择器');
    该方法可以由document及任意页面对象调用 

    获取所有匹配到的页面元素

    document.querySelectorAll('css语法选择器');
    该方法可以由document及任意页面对象调用
    返回值为NodeList (一个类数组结果的对象,使用方式同数组)
    没有匹配到任何结果返回空NodeList对象 ([])

    id名

    可以通过id名直接获取对应的页面元素对象,但是不建议使用

    js选择器运用实例

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>js选择器</title>
        <style>
            #d {
                color: red;
            }
        </style>
    </head>
    <body id="bd">
        <!--注释-->
        <div id="d" class="dd">我是ddd111</div>
        <div id="d" class="dd">我是ddd222</div>
    
        <div class="sup1">
            <div id="div"></div>
        </div>
        <div class="sup2">
            <div id="div"></div>
        </div>
    </body>
    <script>
        // 节点(了解): 在文档(document)中出现的所有内容都是document中的节点
        // 节点(node): 标签节点(元素element) | 注释节点 | 文本节点 | <!doctype>节点
        console.log([bd]) // 文本 注释 文本 标签 文本 标签 文本 标签 文本 标签 文本
    </script>
    <script>
        // js选择器: 将js与html建立起连接
        // js中一般称标签为页面元素
    
        // 1.直接通过id名进行匹配
        console.log(d);  // 两个都可以找到
    
        // 2.getElement系列(最严谨)
        // 所有显示在页面中的内容(展现给用户看的), 都是属于文档(document)对象的内容, 存放在文档中
        // console.log(document)
        // 获取文档中的标签 => document对象通过.语法去获取具体的目标标签元素
        // ① id
        var div = document.getElementById('d');  // 检索得到页面中出现的第一个满足条件的目标
        console.log(">>>", div);
    
        var body = document.getElementById("bd");
        console.log(body);
    
        // 注: getElementById该方法只能由document来调用
        // 原因: 我们需要保证一个文档中一个id只能出现一次, document检索的就是文档,
        // 而某父级标签只能检索自身标签内部区域, document可以保证文档中只能一个id
        // 只出现一次,某父级标签只能保证自身内部区域id不重复,能不能保证与外界不重复?
        // 不能, 所以从安全角度出发, 获取唯一对象的getElementById方法只能由能确定唯一id的
        // 对象来调用, 能被document调用, 不能被sup来调用
    
        // ② 类名
        var divs = document.getElementsByClassName('dd');
        console.log(divs);
        // 两个div在body之中, 上方已经获取了body, 那能否通过body来获取body中的div
        var divs1 = body.getElementsByClassName('dd');
        console.log(divs1);
    
        // ③ 标签名
        var divs = document.getElementsByTagName('div');
        console.log(divs)
    
        console.log('--------------------------------------------------');
    
        // 3.querySelector系列(最方便)
        // 参数: 就是css选择器语法
        // querySelector检索第一个
        var div = document.querySelector('body > .dd');
        console.log(div);
    
        // querySelectorAll检索所有满足结果
        var divs = document.querySelectorAll('body > .dd');
        console.log(divs);
        var divs = body.querySelectorAll('.dd');
        console.log(divs)
    
        var divs = body.querySelectorAll('#d');  // 不严谨
        console.log(divs)
    
    
    </script>
    </html>

    选择器分类

    1. ID选择器
    
    使用ID选择器时,需在前面添加“#”,区分大小写,语法如下:document.querySelector('#id'); //等同于document.getElementById('id')
    
    2. 元素选择器
    
    元素选择器通过指定的标签查询元素,此时querySelectorAll等同于getElementsByTagName,语法如下:document.querySelectorAll('a'); //获取页面上的所有a元素并返回元素
    
    3. 样式类选择器
    
    使用元素的样式类获取一个或一类元素,样式名字前使用“.”(英文句号)开头,语法如下:document.querySelectorAll('.btn'); //获取所有样式类中包含btn类名的元素
    
    4. 分组选择器
    
    使用querySelectorAll不仅可以获取一个或一类元素,还可以同时获取其他类别元素,两种类型之间使用逗号隔开,语法如下:document.querySelectorAll('a,p'); 
    //获取页面上所有a元素和p元素,并通过一个列表返回document.querySelectorAll('.btn,.txt'); //获取页面上所有包含btn和txt样式类名的元素
    
    5. 属性选择器
    
    获取页面上包含指定属性的元素,属性名称可以是元素原生属性和用户自定义属性,语法如下:document.querySelectorAll('a[target="_blank"]'); 
    //获取页面上所有target属性为_blank的a元素document.querySelectorAll('img[data-id]'); //获取页面上所有带有自定义属性data-id的img元素
    
    6. 后代选择器
    
    主要用于选择作为某元素后代的元素,规则左边的选择器一端包含两个或多个用空格分隔的选择器,如div a可以理解为查找所有被div包围的所有a元素,语法如下:document.querySelectorAll('div a'); 
    //获取页面上所有被div包含的a元素document.querySelectorAll('div .btn'); //获取页面上所有被div包含的带有btn样式类名的元素
     
    7. 子元素选择器
    
    后代选择器会将元素底下的所有相关元素都搜索出来,如果想进一步缩小范围,可以使用子元素选择器,只会选择某个元素的一级子元素,子元素用“>”(大于号)表示,代码如下:
    <html>    <div id="first">        <div></div>        <div></div>    </div></html>     <script>    document.querySelectorAll('html>div'); //只返回一个id为first的div元素</script>
     
    8. 相邻兄弟选择器(比较少用)
    
    选择紧接在另一个元素后的元素,而且两者有相同的父元素,相邻兄弟选择器使用“+”(加号),代码如下:
    <div>    <div></div>    <div></div></div><p id="p1"></p><p id="p2"></p><script>    document.querySelectorAll('div+p'); 
    //只返回一个id为p1的p元素</script>
     
    9. 伪类选择器
    
    “:first-child”表示选择元素的第一个子元素,“:last-child”表示选择元素的最后一个子元素,“:nth-child(n)”表示选择元素的第n个子元素。“:first-child”的使用例子,代码如下:
    <div>    <p id="p1"></p>    <p id="p2"></p></div> <script>    document.querySelectorAll('p:first-child'); //只返回一个id为p1的p元素</script>

    闭包

    function outer() {
    var data = {}
    function inner() {
    return data;
    }
    return inner;
    }

    闭包目的:不允许提升变量作用域时,该函数的局部变量需要被其他函数使用
    闭包本质:函数的嵌套,内层函数称之为闭包
    闭包的解决案例:①影响局部变量的生命周期,持久化局部变量;②解决变量污染

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>闭包</title>
    </head>
    <body>
    闭包
    </body>
    <script>
        // 了解知识点
        // 闭包: 局部的函数(被一个函数包裹的函数)
        // 为什么使用闭包:
        // 1.一个函数要使用另一个函数的局部变量
        // 2.闭包会持久化包裹自身的函数的局部变量
        // 3.解决循环绑定
    
        // 函数的嵌套定义
        function outer() {
            var num = 10;
            function inner() {
                // 1.在inner函数中,使用了outer的局部变量num
                return num;
            }
            return inner;
        }
        var innerFn = outer();
        // 2.借助闭包,将局部变量num的生命周期提升了
        var num = innerFn();
        console.log(num);
    
    
    </script>
    </html>

    循环绑定

    .html文件

    <ul>
    <li>列表项</li>
    <li>列表项</li>
    <li>列表项</li>
    </ul>

    .js文件

    var lis = document.querySelector('li');
    for (var i = 0; i < lis.length; i++) {
    lis[i].onclick = function () {
    // 打印列表项的索引
    console.log(i);
    }
    }

    会发生变量污染

    解决方法

    1 获取局部作用域解决   2  闭包解决  3  对象属性解决

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>循环绑定</title>
    </head>
    <body>
    <div class="box">0000000000000000001</div>
    <div class="box">0000000000000000002</div>
    <div class="box">0000000000000000003</div>
    </body>
    <script>
        var divs = document.querySelectorAll(".box");
        /* 存在污染
        for (var i = 0; i < divs.length; i++) {
            // i = 0 | 1 | 2 | 3
            // 循环绑定
            divs[i].onclick = function () {
                console.log("***", i)
            }
        }
        // i = 3
        console.log(">>>", i);
        */
    
        /* 利用块级作用域解决
        for (let i = 0; i < divs.length; i++) {
            // {i=0 <= i} {i=1 <= i} {i=2 <= i}
            // i = 3
            // 循环绑定
            divs[i].onclick = function () {
                console.log("***", i)
            }
        } // for运行结束, i=3会被销毁
        console.log(">>>", i)
        */
    
        // 利用标签的属性解决
        /*
        for (var i = 0; i < divs.length; i++) {
            divs[i].index = i;
            divs[i].onclick = function () {
                // console.log("###", i)
                console.log(this.index)
            }
        }
        */
    
        // 利用闭包处理循环绑定
        for (var i = 0; i < divs.length; i++) {
            (function () {
                var index = i;
                divs[index].onclick = function () {
                    console.log("###", index)
                }
            })()
            /*
            (function (index) {
                divs[index].onclick = function () {
                    console.log("###", index)
                }
            })(i)
             */
            /*
            (function (i) {
                divs[i].onclick = function () {
                    console.log("###", i)
                }
            })(i)
             */
        }
    
    
    </script>
    </html>

    面向对象JS

    属性与方法

    var obj = {}; | var obj = new Object();

    属性

    obj.prop = "";

    方法

    obj.func = function () {}

    删除属性与方法

    delete obj.prop
    delete obj.func

    属性和方法实际使用

    对象: 特征与行为的结合体, 是一个具象的实体
    
    // js对象语法
    var obj = {
    // 属性
    name: 'Zero',
    // 方法
    teach: function () {
     console.log("教学");
    }
    };
    // 对象使用属性与方法, 采用.语法
    console.log(obj.name);
    obj.teach();

    JS中中括号([ ])与 .

    中括号运算符总是能代替点运算符。但点运算符却不一定能全部代替中括号运算符
    中括号运算符可以用字符串变量的内容作为属性名。点运算符不能
    中括号运算符可以用纯数字为属性名。点运算符不能
    中括号运算符可以用js的关键字和保留字作为属性名。点运算符不能

    下面的例子中,a.b表示对象a的属性b,既可以设置也可以读取

    object[key]=>key为常量时,object[key]等价于object.key,例如:a.b == a['b'] 

    特殊的,object[key] 中key为变量时,只能用中括号形式

    var a = {};
     // a.b = 1; 
    a['b'] = 1; 
    c = a.b; 
    // c = a['b'];
    alert(c);

    标识符是否合法对两种用法的影响

    var obj = {}; 
    // 为obj添加一个属性name,name是合法的标识符,即也可以通过obj.name方式来定义
    
    obj['name'] = 'jack'; 
    
    // 为obj添加一个属性2a,2a不是合法的标识符(不能以数字开头),不能通过obj.2a来定义
    
    obj['2a'] = 'test';
    
    var obj = {name:'jack'};
    obj['2a'] = 'test';
    obj['name']; // --> jack 
    obj['2a']; // --> test (不能通过obj.2a获取)

    总结:常量用点,变量就用中括号

    运算符左侧应当是一个表达式,它返回一个对象。
    对于点(.)来说,右侧必须是一个以属性名称命名的简单标识符。
    对于方括号([])来说,方括号里必须是一个计算结果为字符串的表达式,这个字符串就是属性的名字

    当通过点运算符(.)方法对象属性时,属性名用一个标识符来表示。标识符必须直接出现在js程序中,它们不是数据类型,因此程序无法修改它们。
    反过来讲,当通过[]来方式对象的属性时,属性名通过字符串表示。字符串是js的数据类型,在程序运行时可以修改和创建它们

    <script type="text/javascript">
    var addr = "";
    for(i=0;i<4;i++){
    addr += cutomer["address" + i] + "
    ";
    }
    </script>

    这段代码读取customer对象的address0,adddress1,address2,adddress3属性,并将他们连接起来

    类字典结构使用

    结构

    var dict = {name: "zero", age: 18}

    拓展

    var dict = {"my-name": "zero", fn: function () {}, fun () {}}

    使用

    dict.name | dict["my-name"] | dict.fn()

    构造函数(ES5)

    // 构造函数: 声明与普通函数一样, 只是函数名采用大驼峰命名规则
    function Person(name) {  // 类似于python中的类一样来使用
       // 构造函数内部属性方式不同于普通函数
       this.name = name;  // this代表Person构造函数实例化出的所有具体对象中的某一个
       this.teach = function () {
           console.log(this.name + "正在教学");
       }
    }
    // 如何使用构造函数中的属性与方法
    // 1. 通过构造函数实例化出具体对象
    // 2. 通过对象.语法调用属性与方法
    var p1 = new Person("杨虎虎");  // name: 杨虎虎
    var p2 = new Person("刘xx");  // name: 刘xx
    console.log(p1.name);
    console.log(p2.name);
    p1.teach();
    p2.teach();
    
    
    为什么要用new?
    
    new  会创建  pre 的对象,
    但是没有 new 的话就没有没有可返回的值或对象了,所以是  undefined。
    如果不想new 新的对象的话,可以在 pre 的方法里 返回一个值或对象。
    function pre(){
        this.radius = Math.random();
        return this.radius;
    }
    
    加 new 会把这个函数当作是一个构造器,返回一个对象。
    不加的话,就是调用一个普通的函数,结果视函数返回值而定。 
    有new,就返回对象,不管函数返回值如何。
    无new,就看函数返回值。
    构造函数最好返回 this 或者无返回值, 否则容易混淆。

    类及继承(ES6)

    // ES6
    // 引入了类
    class Student {  // 类, 可以实例化对象, 但实例化出的对象需要加以区分
    // 需要构造器(构造函数)来完成对象的声明与初始化
    // ES6规定方法的语法
    constructor (name) {
       // 属性在构造器中声明并完成初始化
       this.name = name;
    }
    // 类中规定普通方法
    study () {
       console.log(this.name + "正在学习");
    }
    // 类方法
    static fn() {
    console.log("我是类方法")
      }
    }
    // 1.实例化类的对象
    let stu1 = new Student("嘿嘿");
    // 2.使用属性与方法
    console.log(stu1.name);
    stu1.study();
    
    let stu2 = new Student("嘻嘻");
    console.log(stu2.name);
    stu2.study();
    
    Student.fn()
    
    <script>
    // 类方法
    class Tool { // 功能类(工具类)中的方法都定义为类方法
    static max (num1, num2) {
    return num1 > num2 ? num1 : num2;
    }
    }
    // 通过Tool类来求两个数中的大值, 需要Tool类的对象出现吗? 不需要 => 功能有类直接使用
    console.log(Tool.max(666, 888));
    
    
    // throw "自定义异常";
    // console.log("上面如果出现了异常, 逻辑将会被强制停止");
    // var num = 10 / 0;
    // console.log(num)
    </script>
    

     

  • 相关阅读:
    031-进阶(日志)
    Django 路由系统
    C++ 面向对象(接口-抽象类)
    C++ 面向对象(多态)
    C++ 面向对象(数据抽象)
    三十、首页列表显示全部问答,完成问答详情页布局
    二十九、制作首页的显示列表
    二十八、发布功能完成
    二十七、登录之后更新导航
    二十六、完成登录功能,用session记住用户名
  • 原文地址:https://www.cnblogs.com/596014054-yangdongsheng/p/10142691.html
Copyright © 2020-2023  润新知