1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        你不知道的16個(gè)js原生函數(shù)和屬性的區(qū)別

        共 25912字,需瀏覽 52分鐘

         ·

        2021-08-10 06:23


        點(diǎn)擊上方 程序員成長指北,關(guān)注公眾號

        回復(fù)1,加入高級Node交流群

        前言

        原生內(nèi)置了很多API, 作用類似,卻也有差千差萬別,了解其區(qū)別,掌握前端基礎(chǔ),是修煉上層,成為前端高級工程師的必備知識(shí),讓我們一起來分類歸納,一起成長吧。

        上一篇前端基礎(chǔ)好文:那些你熟悉而又陌生的函數(shù)[2]

        屬性獲取 keysgetOwnPropertyNamesgetOwnPropertySymbols

        Object.keys[3]

        返回一個(gè)由一個(gè)給定對象的自身可枚舉屬性組成的數(shù)組,數(shù)組中屬性名的排列順序和正常循環(huán)遍歷該對象時(shí)返回的順序一致 。

        Object.getOwnPropertyNames[4]

        返回一個(gè)由指定對象的所有自身屬性的屬性名(包括不可枚舉屬性但不包括Symbol值作為名稱的屬性)組成的數(shù)組。

        Object.getOwnPropertySymbols[5]

        一個(gè)給定對象自身的所有 Symbol 屬性的數(shù)組。

        Reflect.ownKeys[6]

        返回一個(gè)由目標(biāo)對象自身的屬性鍵組成的數(shù)組。
        等同于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))

        例子

        const symbolSalary = Symbol.for("salary");
        const symbolIsAnimal = Symbol.for("isAnimal");
        const symbolSay = Symbol.for("say");

        function Person(age, name){
           this.age = age;
           this.name = name;

           this.walk = function () {
               console.log("person:walk");
           }
        }

        // 原型方法
        Person.prototype.say = function(words){
           console.log("say:", words);
        }
        Person.prototype[symbolSay] = function(words){
           console.log("symbolSay", words);
        }

        // 原型屬性
        Person.prototype[symbolIsAnimal] = true;
        Person.prototype.isAnimal = true;

        const person = new Person(100"程序員");

        person[symbolSalary] = 6000;
        person["sex"] = "男";

        // sex 不可枚舉
        Object.defineProperty(person, "sex", {
           enumerablefalse
        });

        Object.defineProperty(person, symbolSalary, {
           enumerablefalse// 無效的設(shè)置 
           value999
        });

        const keys = Object.keys(person);
        const names = Object.getOwnPropertyNames(person);
        const symbols = Object.getOwnPropertySymbols(person);
        const ownKeys = Reflect.ownKeys(person);

        console.log("keys", keys);  // [ 'age', 'name', 'walk' ]
        console.log("getOwnPropertyNames", names); // [ 'age', 'name', 'walk', 'sex' ]
        console.log("getOwnPropertySymbols", symbolSalary); // [ Symbol(salary) ]
        console.log("ownKeys", ownKeys); // [ 'age', 'name', 'walk', 'sex', Symbol(salary) ]


        console.log("--------")
        console.log(person.isAnimal);  // true
        console.log(person[symbolIsAnimal]); // true
        console.log(person[symbolSalary]);  // 999
        person[symbolSay]("hello world"); // symbolSay hello world
        person.say("hello world"); // say: hello world
        person.walk(); // person:walk
        復(fù)制代碼

        總結(jié)

        1. Object.keys:則返回的是所有可枚舉屬性鍵,也就是屬性下的enumerable: true。但不包括Symbol值作為名稱的屬性鍵。

        2. Object.getOwnPropertyNames:返回的是對象所有自己的屬性鍵 ,包括不可枚舉屬性但不包括Symbol值作為名稱的屬性鍵。

        3. Object.getOwnPropertySymbols: 方法返回一個(gè)給定對象自身的所有 Symbol 屬性鍵的數(shù)組。

        4. Reflect.ownKeys: 返回一個(gè)由目標(biāo)對象自身的屬性鍵組成的數(shù)組。等同于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))。

        節(jié)點(diǎn)位置關(guān)系 Node.containsNode.compareDocumentPosition

        Node.compareDocumentPosition[7]

        比較當(dāng)前節(jié)點(diǎn)與任意文檔中的另一個(gè)節(jié)點(diǎn)的位置關(guān)系

        語法 compareMask = node.compareDocumentPosition( otherNode )

        返回值是一個(gè)具有以下值的位掩碼:

        常量名 十進(jìn)制值 含義
        DOCUMENT_POSITION_DISCONNECTED 1 不在同一文檔中
        DOCUMENT_POSITION_PRECEDING 2 otherNode在node之前
        DOCUMENT_POSITION_FOLLOWING 4 otherNode在node之后
        DOCUMENT_POSITION_CONTAINS 8 otherNode包含node
        DOCUMENT_POSITION_CONTAINED_BY 16 otherNode被node包含
        DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC 32 待定

        在一些場景下,可能設(shè)置了不止一位比特值。比如 otherNode 在文檔中是靠前的且包含了 Node, 那么DOCUMENT_POSITION_CONTAINS 和 DOCUMENT_POSITION_PRECEDING 位都會(huì)設(shè)置,所以結(jié)果會(huì)是 0x0A 即十進(jìn)制下的 10。

        看代碼:
        結(jié)果是:20

        1. child 在 parent之后,賦值得4
        2. child 被 parent包含,賦值的16

        4 + 16 = 20

            <div id="parent">
                <div id="child"></div>
            </div>

            <script>

                const pEl = document.getElementById("parent");
                const cEl = document.getElementById("child");
                console.log(pEl.compareDocumentPosition(cEl));  // 20

            </script>

        復(fù)制代碼

        Node.contains[8]

        返回的是一個(gè)布爾值,來表示傳入的節(jié)點(diǎn)是否為該節(jié)點(diǎn)的后代節(jié)點(diǎn)

        基本等于compareDocumentPosition的 | DOCUMENT_POSITION_CONTAINED_BY | 16 |otherNode被node包含 |

        總結(jié)

        1. compareDocumentPosition 返回的是數(shù)字,帶組合意義的數(shù)據(jù),不僅僅可以返回包含,還可以返回在之前之后等信息
        2. contains 返回的是布爾值,僅僅告訴你是否有包含關(guān)系

        取文本 innerTexttextContent

        HTMLElement.innerText[9]

        解析過程:

        1. 對HTML標(biāo)簽進(jìn)行解析;
        2. 對CSS樣式進(jìn)行帶限制的解析和渲染;
        3. 將ASCII實(shí)體轉(zhuǎn)換為對應(yīng)的字符;
        4. 剔除格式信息(如\t、\r、\n等),將多個(gè)連續(xù)的空格合并為一個(gè)

        Node.textContent[10]

        解析過程:

        1. 對HTML標(biāo)簽進(jìn)行剔除;
        2. 將ASCII實(shí)體轉(zhuǎn)換為相應(yīng)的字符。

        需要注意的是:

        1. 對HTML標(biāo)簽是剔除不是解析,也不會(huì)出現(xiàn)CSS解析和渲染的處理,因此<br/>等元素是不生效的。
        2. 不會(huì)剔除格式信息和合并連續(xù)的空格,因此\t、\r、\n和連續(xù)的空格將生效

        例子

            <p id="source">
                <style>
                    #source {
                        color: red;
                    }
                </style>

                Take a look at<br>how this text<br>is interpreted
                below.
                <span style="display:none">HIDDEN TEXT</span>
            </p>
            
             <h3>Result of textContent:</h3>
            <textarea id="textContentOutput" rows="12" cols="50" readonly>...</textarea>
            <h3>Result of innerText:</h3>
            <textarea id="innerTextOutput" rows="12" cols="50" readonly>...</textarea>

            <script>
                const source = document.getElementById('source');
                const textContentOutput = document.getElementById('textContentOutput');
                const innerTextOutput = document.getElementById('innerTextOutput');

                textContentOutput.innerHTML = source.textContent;
                innerTextOutput.innerHTML = source.innerText;
            </script>

        復(fù)制代碼

        看看結(jié)果:

        image.png

        總結(jié)

        1. innerText是會(huì)解析css的,<br/>有效,剔除格式信息(如\t、\r、\n等),將多個(gè)連續(xù)的空格合并為一個(gè)。
        2. textContent是剔除html標(biāo)簽,<br/>無效,\t、\r、\n和連續(xù)的空格將生效。

        節(jié)點(diǎn)取值 value , nodeValue

        Node.nodeValue[11]

        • 對于textcomment, 和 CDATA 節(jié)點(diǎn)來說, nodeValue返回該節(jié)點(diǎn)的文本內(nèi)容.
        • 對于 attribute 節(jié)點(diǎn)來說, 返回該屬性的屬性值.

        對應(yīng)著下面表格的 nodeType的值 text 3,4,8

        常量 nodeType 值 描述
        Node.ELEMENT_NODE 1 一個(gè) 元素 節(jié)點(diǎn),例如

        || Node.TEXT_NODE | 3 | Element 或者 Attr 中實(shí)際的 文字 || Node.CDATA_SECTION_NODE | 4 | 一個(gè) CDATASection,例如 <!CDATA[[ … ]]>。|| Node.PROCESSING_INSTRUCTION_NODE | 7 | 一個(gè)用于XML文檔的 ProcessingInstruction (en-US) ,例如 聲明。|| Node.COMMENT_NODE | 8 | 一個(gè) Comment 節(jié)點(diǎn)。|| Node.DOCUMENT_NODE | 9 | 一個(gè) Document 節(jié)點(diǎn)。|| Node.DOCUMENT_TYPE_NODE | 10 | 描述文檔類型的 DocumentType 節(jié)點(diǎn)。例如 就是用于 HTML5 的。|| Node.DOCUMENT_FRAGMENT_NODE | 11 | 一個(gè) DocumentFragment 節(jié)點(diǎn) |

        value

        特定的一些HTMLElement元素,用value屬性獲取其值。常見的有value屬性的元素如下:

        • HTMLInputElement[12] <input value="1" />
        • HTMLTextAreaElement[13] <textarea value= "你哈" />
        • HTMLButtonElement[14] <button value= "提交" />
        • HTMLDataElement[15] <data value="21053">圣女果</data>
        • HTMLSelectElement[16] <select><option value ="volvo">Volvo</option>
        • HTMLOptionElement[17] <select><option value ="volvo">Volvo</option>
        • HTMLParamElement[18]
        <object classid="clsid:F08DF954-8592-11D1-B16A-00C0F0283628" id="Slider1" width="100" height="50">    
             <param name="BorderStyle" value="1" />
        </object>
        復(fù)制代碼
        • HTMLProgressElement[19] <progress value="22" max="100"></progress>

        總結(jié)

        1. nodeValue 是文本節(jié)點(diǎn),屬性節(jié)點(diǎn),注釋節(jié)點(diǎn)等類型的節(jié)點(diǎn)用來取值的方法
        2. vlaue是特定的元素節(jié)點(diǎn)用來取值的方法

        節(jié)點(diǎn)復(fù)制 adoptNodeimportNodecloneNode

        Document.adoptNode[20]

        將外部文檔的一個(gè)節(jié)點(diǎn)拷貝一份,然后可以把這個(gè)拷貝的節(jié)點(diǎn)插入到當(dāng)前文檔中.

        Document.importNode[21]

        從其他的document文檔中獲取一個(gè)節(jié)點(diǎn)。該節(jié)點(diǎn)以及它的子樹上的所有節(jié)點(diǎn)都會(huì)從原文檔刪除 , 并且它的ownerDocument 屬性會(huì)變成當(dāng)前的document文檔。之后你可以把這個(gè)節(jié)點(diǎn)插入到當(dāng)前文檔中。

        Node.cloneNode[22]

        生成節(jié)點(diǎn)的一個(gè)副本。

        實(shí)際上 Document 是繼承自 Node, 也具備cloneNode方法。

        這里提一個(gè)問題:
        Document.adoptNodeDocument.importNode是操作外部文檔的,那么操作所在的文檔會(huì)有什么效果呢?

        Node.cloneNode 有一個(gè)boolean類型的可選參數(shù)deep

        • true: 則該節(jié)點(diǎn)的所有后代節(jié)點(diǎn)也都會(huì)被克隆
        • false: 則只克隆該節(jié)點(diǎn)本身.

        注意

        1. cloneNode deep參數(shù)在不同版本的瀏覽器實(shí)現(xiàn)中,默認(rèn)值可能不一樣, 所以強(qiáng)烈建議寫上值。
        2. cloneNode 會(huì)克隆一個(gè)元素節(jié)點(diǎn)會(huì)拷貝它所有的屬性以及屬性值,當(dāng)然也就包括了屬性上綁定的事件(比如onclick="alert(1)"),但不會(huì)拷貝那些使用addEventListener()方法或者node.onclick = fn這種用JavaScript動(dòng)態(tài)綁定的事件

        總結(jié)

        1. adoptNode 從外部文檔進(jìn)行拷貝
        2. importNode 從外部文檔進(jìn)行拷貝,并從外部文檔刪除
        3. cloneNode 從本文檔進(jìn)行復(fù)制,有淺復(fù)制和深復(fù)制

        父節(jié)點(diǎn) childNodes , children

        Node.childNodes[23]

        節(jié)點(diǎn)的子節(jié)點(diǎn)集合,包括元素節(jié)點(diǎn)、文本節(jié)點(diǎn)還有屬性節(jié)點(diǎn)

        ParentNode.children[24]

        返回的只是節(jié)點(diǎn)的元素節(jié)點(diǎn)集合, 即 nodeType為1的節(jié)點(diǎn)。

        例子

        來實(shí)際看一段代碼:

            <div id="root">
                1
                <span>2</span>
                3
                <!-- <div></div> -->
                <!CDATA[[ 4 ]]>
            </div>

            <script>
                const rootEl = document.getElementById("root");
                console.log(rootEl.children);
                console.log(rootEl.childNodes);
            </script>

        復(fù)制代碼

        返回結(jié)果截圖:

        Node.parentNodeNode.parentElement也是同樣的道理。

        總結(jié)

        1. children只返回元素節(jié)點(diǎn),也就是 nodeType為1的節(jié)點(diǎn)
        2. childNodes 返回所有類型的節(jié)點(diǎn)

        添加節(jié)點(diǎn) appendappendChild

        node.appendChild[25]

        將一個(gè)節(jié)點(diǎn)附加到指定父節(jié)點(diǎn)的子節(jié)點(diǎn)列表的末尾處

        ParentNode.append[26]

        方法在 ParentNode的最后一個(gè)子節(jié)點(diǎn)之后插入一組 Node 對象或 DOMString 對象。被插入的 DOMString 對象等價(jià)為 Text 節(jié)點(diǎn).

        例子

        我們一次append三個(gè)節(jié)點(diǎn),其中兩個(gè)文本節(jié)點(diǎn),一個(gè)div節(jié)點(diǎn)。

          <div id="root"></div>
          <script>
            function createEl(type, innerHTML){
                const el = document.createElement(type);
                el.innerHTML = innerHTML;
                return el;
            }
            const rootEl = document.getElementById("root");

            rootEl.append("我們", createEl("div""都是"), "好孩子");
          </script>

        復(fù)制代碼
        image.png

        總結(jié)

        • ParentNode.append()允許追加 DOMString 對象,而 Node.appendChild() 只接受 Node 對象。
        • ParentNode.append() 沒有返回值,而 Node.appendChild() 返回追加的 Node 對象。
        • ParentNode.append() 可以追加多個(gè)節(jié)點(diǎn)和字符串,而 Node.appendChild() 只能追加一個(gè)節(jié)點(diǎn)。

        簡直說, append強(qiáng)大太多了。

        文檔可見狀態(tài) Document.hiddenDocument.visibilityState

        document.hidden[27]

        返回布爾值,表示頁面是(true)否(false)隱藏。

        Document.visibilityState[28]

        返回document的可見性, 由此可以知道當(dāng)前文檔(即為頁面)是在背后, 或是不可見的隱藏的標(biāo)簽頁,或者(正在)預(yù)渲染.可用的值如下:

        • 'visible' : 此時(shí)頁面內(nèi)容至少是部分可見. 即此頁面在前景標(biāo)簽頁中,并且窗口沒有最小化.
        • 'hidden' : 此時(shí)頁面對用戶不可見. 即文檔處于背景標(biāo)簽頁或者窗口處于最小化狀態(tài),或者操作系統(tǒng)正處于 '鎖屏狀態(tài)' .
        • 'prerender' : 頁面此時(shí)正在渲染中, 因此是不可見的 . 文檔只能從此狀態(tài)開始,永遠(yuǎn)不能從其他值變?yōu)榇藸顟B(tài) .注意: 瀏覽器支持是可選的.

        當(dāng)此屬性的值改變時(shí), 會(huì)遞交 visibilitychange 事件給Document.

        例子

        我們先輸出當(dāng)前狀態(tài),然后點(diǎn)擊別的tab,等下再點(diǎn)擊回來。

              console.log(
                "visibilityState:",
                document.visibilityState,
                " hidden:",
                document.hidden,
              );
              console.log("");
              document.addEventListener("visibilitychange"function () {
                console.log(
                  "visibilityState:",
                  document.visibilityState,
                  " hidden:",
                  document.hidden
                );
              });
        復(fù)制代碼
        image.png

        我們?nèi)粘?梢杂?code style="margin: 3px;padding: 3px;font-size: 14px;border-radius: 4px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(155, 110, 35);background-color: rgb(255, 245, 227);">visibilitychange來監(jiān)聽當(dāng)前頁面處于隱藏時(shí),去清除定時(shí)器或頁面中的動(dòng)畫, 停止音樂視頻等的播放。

        我還想到一個(gè)有意思的

        1. 廣告倒計(jì)時(shí)

        你離開后,不算倒計(jì)時(shí),會(huì)不會(huì)被罵死

        1. 閱讀某些協(xié)議

        你離開后,停止倒計(jì)時(shí)

        總結(jié)

        1. hidden 與 visibilityState 返回值不同,一個(gè)是布爾值,一個(gè)是字符串
        2. visibilityState 的狀態(tài)多一種 prerender, 其對應(yīng)的hidden的值是true
        3. visibilityState e有相關(guān)的事件

        函數(shù)調(diào)用 callapplybind

        Function.prototype.call[29]

        使用一個(gè)指定的 this 值和單獨(dú)給出的一個(gè)或多個(gè)參數(shù)來調(diào)用一個(gè)函數(shù)

        Function.prototype.apply[30]

        調(diào)用一個(gè)具有給定this值的函數(shù),以及以一個(gè)數(shù)組(或類數(shù)組對象)的形式提供的參數(shù)

        Function.prototype.bind[31]

        方法創(chuàng)建一個(gè)新的函數(shù),在 bind() 被調(diào)用時(shí),這個(gè)新函數(shù)的 this 被指定為 bind() 的第一個(gè)參數(shù),而其余參數(shù)將作為新函數(shù)的參數(shù),供調(diào)用時(shí)使用

        例子

        function sum(...args{
            const total = args.reduce((s, cur) => {
                return s + cur;
            }, 0);

            return (this.base || 0) + total;
        }

        const context = {
            base1000
        };

        const bindFun = sum.bind(context, 12);

        const callResult = sum.call(context, 1234);
        const applyResult = sum.apply(context, [1234]);
        const bindResult = bindFun(34);


        console.log("call:", callResult);  // 1010
        console.log("apply:", applyResult); // 1010 
        console.log("bind:", bindResult); // 1010
        復(fù)制代碼

        總結(jié)

        相同點(diǎn),都能改變被調(diào)用函數(shù)的this指向。

        1. call: 第二個(gè)參數(shù)開始,可以接收任意個(gè)參數(shù)
        2. apply: 第二個(gè)參數(shù),必須是數(shù)組或者類數(shù)組
        3. bind: 第二個(gè)參數(shù)開始,可以接收任意個(gè)參數(shù) , 返回的是一個(gè)新的函數(shù)

        注意點(diǎn):

        1. bind調(diào)用多次,this指向第一次第一個(gè)參數(shù)

        log 調(diào)用了兩次bind, 第一次bind{ val: 1 }, 第二次bind{ val: 2 }, 輸出的this是一次bind的上下文

        function log() {
            console.log("this"this);
        }
        console.log(log.bind({ val1 }).bind({ val2 })())  // { val: 1 }

        復(fù)制代碼

        再看一段類似的代碼:
        雖然this的指向不會(huì)再變改變,但是參數(shù)還是繼續(xù)接受, arguments 長度為2, 第一次bind的1,第二次bind的 2 , 都照單全收。


        function log() {
            console.log("this"this);   // { val: 1 }
            console.log("arguments"arguments);  // { '0': 1, '1': 2 }
        }

        console.log(log.bind({ val1 }, 1).bind({ val2 }, 2)())  // 1
        復(fù)制代碼

        字符串截取 substrsubstring

        String.prototype.substr[32]

        返回一個(gè)字符串中從指定位置開始到指定字符數(shù)的字符

        語法:第二參數(shù),是需要截取的長度

        str.substr(start[, length])

        String.prototype.substring[33]

        返回一個(gè)字符串在開始索引到結(jié)束索引之間的一個(gè)子集, 或從開始索引直到字符串的末尾的一個(gè)子集。

        語法:第二參數(shù),結(jié)束索引

        str.substring(indexStart[, indexEnd])

        例子

        提示:

        1. 兩個(gè)參數(shù)都沒設(shè)置的時(shí)候,效果相同
        2. 第一個(gè)參數(shù)是**大于等于0的整數(shù)**,沒設(shè)置第二參數(shù)的時(shí)候,效果相同
        const str = "我們都是好孩子";

        console.log(str.substr())  // 我們都是好孩子
        console.log(str.substring()) // 我們都是好孩子

        console.log(str.substr(1))  // 們都是好孩子
        console.log(str.substring(1)) // 們都是好孩子

        console.log(str.substr(-1))  // 子
        console.log(str.substring(-1)) // 我們都是好孩子

        console.log(str.substr(12))  // 們都
        console.log(str.substring(12))  // 們
        復(fù)制代碼

        總結(jié)

        1. substr 第二個(gè)參數(shù)是需要截取的長度
        2. substring 第二個(gè)參數(shù)是結(jié)束索引值的
        3. 沒指定參數(shù)或者第一個(gè)參數(shù)是大于等于0的整數(shù)時(shí),效果相同
        4. 第一個(gè)參數(shù)是負(fù)數(shù)或者第二個(gè)參數(shù)是負(fù)數(shù),處理規(guī)則不通

        具體參見 substr[34]和 substring[35]

        遍歷 for offor in

        for in

        獲取enumerable:true的屬性鍵

        for of

        遍歷屬性值。不受到enumerable限制。

        例子

        1. 在數(shù)組原型上增加了方法`gogo`, `for in`結(jié)果中出現(xiàn)了,而 `for of`結(jié)果沖未出現(xiàn)。
        2. 定義了 屬性2不能被遍歷, `for in`結(jié)果中未出現(xiàn),而 `for of`結(jié)果中出現(xiàn)了。
        // 原型上增加方法
        Array.prototype.gogo = function(){
            console.log("gogo");
        }

        var a = [1,2,3];

        // key值2不可以枚舉
        Object.defineProperty(a, 2, {
            enumerablefalse
        });
        Object.defineProperty(a, "2", {
            enumerablefalse
        });

        for(let p in a){
            // 索引被遍歷出來是字符串類型
            console.log(p, typeof p); // 0 string; 1 string; gogo string
        }

        console.log("---")

        for(let v of a){
            console.log(v);  // 1 2 3
        }
        復(fù)制代碼

        總結(jié)

        for in

        1. 獲取enumerable:true的屬性鍵。
        2. 可以遍歷對象。
        3. 可以獲取原型上的屬性鍵。
        4. 數(shù)字屬性鍵被遍歷出來是字符串。比如索引值

        for of:

        1. 遍歷屬性值。不受到enumerable限制。
        2. 可遍歷數(shù)組。一般不可以遍歷對象,如果實(shí)現(xiàn)了Symbol.iterator,可以遍歷。如Array,Map,Set,String,TypedArray,arguments 對象等等
        3. 不能獲取原型上的值

        當(dāng)前時(shí)間 Date.now()Performance.now()

        Date.now\(\)[36]

        方法返回自 1970 年 1 月 1 日 00:00:00 (UTC) 到當(dāng)前時(shí)間的毫秒數(shù)。

        Performance.now[37]

        獲取當(dāng)前的時(shí)間戳的值(自創(chuàng)建上下文以來經(jīng)過的時(shí)間),其值是一個(gè)精確到毫秒的 DOMHighResTimeStamp[38].

        <!DOCTYPE html>
        <html lang="en">

        <head>
            <script>
                console.log("p1", performance.now())
            </script>

        </head>

        <body>

            <script>
                console.log("p2", performance.now());

                setTimeout(() => {
                    console.log("p3", performance.now());
                }, 1000)
            </script>

        </body>

        </html>

        復(fù)制代碼
        image.png

        總結(jié)

        1. Date.now()的基準(zhǔn)是 1970 年 1 月 1 日 00:00:00 (UTC), 而Performance.now是上下文創(chuàng)建。
        2. Date.now()返回的是整數(shù),Performance.now返回的是double類型
        3. 理論上Performance.now精度更高

        域名信息 hosthostname

        location.host[39]

        其包含:主機(jī)名,如果 URL 的端口號是非空的,還會(huì)跟上一個(gè) ':' ,最后是 URL 的端口號

        location.hostname

        返回域名

        例子

        https與http的默認(rèn)端口號,是不會(huì)被 host包含的,看下面的代碼

        https://developer.mozilla.org:443 的host是 developer.mozilla.org, 因?yàn)?43是https的默認(rèn)端口。

              var anchor = document.createElement("a");

              anchor.href = "https://developer.mozilla.org:443/en-US/Location.host";      
              console.log(anchor.host == "developer.mozilla.org:443"// false
              console.log(anchor.host == "developer.mozilla.org"// true

              console.log(anchor.hostname == "developer.mozilla.org:443"); // false
              console.log(anchor.hostname == "developer.mozilla.org");  // true

              anchor.href = "https://developer.mozilla.org:4097/en-US/Location.host";
              console.log(anchor.host == "developer.mozilla.org:4097")  // true
              console.log(anchor.hostname == "developer.mozilla.org")  // true
        復(fù)制代碼

        總結(jié)

        1. 默認(rèn)端口下, host等于hostname
        2. host額外包含端口號

        事件注冊 onaddEventListener

        內(nèi)聯(lián)事件

        注冊事件。

        EventTarget.addEventListener[40]

        方法將指定的監(jiān)聽器注冊到 EventTarget 上,當(dāng)該對象觸發(fā)指定的事件時(shí),指定的回調(diào)函數(shù)就會(huì)被執(zhí)行。

        例子

        分別注冊兩次onclick和click事件,onclick只輸出一次,click輸出兩次.

           <button id="btn" >點(diǎn)我</button>

            <script>

                const btnEl = document.getElementById("btn");

                btnEl.onclick = () => console.log("onclick"1);
                btnEl.onclick = () => console.log("onclick"1);

                btnEl.addEventListener("click", ()=> console.log("click"1));
                btnEl.addEventListener("click", ()=> console.log("click"2));

            </script>

        復(fù)制代碼
        image.png

        總結(jié)

        1. 內(nèi)聯(lián)事件是覆蓋型,只能使用事件冒泡,addEventListener支持多個(gè)事件處理程序,并支持事件捕獲。

        2. 內(nèi)聯(lián)事件特定情況下可以被Node.cloneNode復(fù)制,addEventListener的不行
          更多細(xì)節(jié)參見 Node.cloneNode[41]

        3. addEventListener為DOM2級事件綁定,onclick為DOM0級事件綁定

        按鍵時(shí)間 keypresskeydown

        keypress[42]

        當(dāng)按下產(chǎn)生字符值的鍵時(shí)觸發(fā)按鍵事件。產(chǎn)生字符值的鍵的示例有字母鍵、數(shù)字鍵和標(biāo)點(diǎn)鍵。不產(chǎn)生字符值的鍵的例子是修改鍵,如 Alt、 Shift、 Ctrl 或 Meta。

        不再推薦使用此功能。盡管一些瀏覽器可能仍然支持它,但它可能已經(jīng)從相關(guān)的 web 標(biāo)準(zhǔn)中刪除

        keydown[43]

        與keypress事件不同,無論是否生成字符值,所有鍵都會(huì)觸發(fā) keydown 事件。

        例子

        輸入123,keydown和keypress的值keyCode一樣

        image.png

        總結(jié)

        1. 觸發(fā)順序keydown -> keypress
        2. keydown:當(dāng)用戶按下鍵盤上的任意鍵時(shí)觸發(fā);
        3. keypress:當(dāng)用戶按下鍵盤上的字符鍵時(shí)觸發(fā);對中文輸入法支持不好,無法響應(yīng)中文輸入
        4. keypress的keyCode與keydown不是很一致;

        異步加載腳本 defer,async

        defer

        異步加載,按照加載順序執(zhí)行腳本的

        async

        異步加載,亂序執(zhí)行腳本。

        這個(gè)一圖勝千文

        image.png

        例子

        四個(gè)script標(biāo)簽,兩個(gè)async,兩個(gè)defer。
        代碼內(nèi)容如下:

        • async1:console.log("async1");
        • async2:console.log("async2");
        • defer1:console.log("defer1");
        • defer2:console.log("defer2");
            <script src="./async1.js" async ></script>
            <div>
                sdfsdfsdfsdfsdfsdfd
            </div>
            <script src="./async2.js" async ></script>

            <script src="./defer1.js" defer ></script>
            <script src="./defer2.js" defer ></script>
        復(fù)制代碼
        image.png
        image.png

        從上面可以看出,有時(shí)候 async2會(huì)比async1輸出早,defer的輸出也可能比async的輸出早。但是defer的輸出一定 defer1然后defer2

        總結(jié)

        1. 都是異步加載,defer會(huì)按照加載順序執(zhí)行,async亂序執(zhí)行

        JS魔法堂:被玩壞的innerHTML、innerText、textContent和value屬性[44]
        keydown,keypress,keyup三者之間的區(qū)別[45]


        關(guān)于本文

        作者:云的世界

        https://juejin.cn/post/6982742095375597575


        如果覺得這篇文章還不錯(cuò)
        點(diǎn)擊下面卡片關(guān)注我
        來個(gè)【分享、點(diǎn)贊、在看】三連支持一下吧

           “分享、點(diǎn)贊在看” 支持一波 

        瀏覽 175
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            成人国产片女人爽到高潮 | 五月天操逼 | 五月丁香六月婷婷综合免费 | 国产精品嫩草影院88av漫画 | 91大片成人网∝ | 日韩3级片 | 美女美穴18q | 天天操 夜夜操 | 国产夫妻操逼视频 | 亚洲无码在线影院 |