<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 25912字,需瀏覽 52分鐘

           ·

          2021-08-10 06:23


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

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

          前言

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

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

          屬性獲取 keysgetOwnPropertyNamesgetOwnPropertySymbols

          Object.keys[3]

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

          Object.getOwnPropertyNames[4]

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

          Object.getOwnPropertySymbols[5]

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

          Reflect.ownKeys[6]

          返回一個由目標對象自身的屬性鍵組成的數(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: 方法返回一個給定對象自身的所有 Symbol 屬性鍵的數(shù)組。

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

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

          Node.compareDocumentPosition[7]

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

          語法 compareMask = node.compareDocumentPosition( otherNode )

          返回值是一個具有以下值的位掩碼:

          常量名 十進制值 含義
          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 位都會設(shè)置,所以結(jié)果會是 0x0A 即十進制下的 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]

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

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

          總結(jié)

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

          取文本 innerTexttextContent

          HTMLElement.innerText[9]

          解析過程:

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

          Node.textContent[10]

          解析過程:

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

          需要注意的是:

          1. 對HTML標簽是剔除不是解析,也不會出現(xiàn)CSS解析和渲染的處理,因此<br/>等元素是不生效的。
          2. 不會剔除格式信息和合并連續(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是會解析css的,<br/>有效,剔除格式信息(如\t、\r、\n等),將多個連續(xù)的空格合并為一個。
          2. textContent是剔除html標簽,<br/>無效,\t、\r、\n和連續(xù)的空格將生效。

          節(jié)點取值 value , nodeValue

          Node.nodeValue[11]

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

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

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

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

          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é)點,屬性節(jié)點,注釋節(jié)點等類型的節(jié)點用來取值的方法
          2. vlaue是特定的元素節(jié)點用來取值的方法

          節(jié)點復(fù)制 adoptNodeimportNodecloneNode

          Document.adoptNode[20]

          將外部文檔的一個節(jié)點拷貝一份,然后可以把這個拷貝的節(jié)點插入到當前文檔中.

          Document.importNode[21]

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

          Node.cloneNode[22]

          生成節(jié)點的一個副本。

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

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

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

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

          注意

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

          總結(jié)

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

          父節(jié)點 childNodes , children

          Node.childNodes[23]

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

          ParentNode.children[24]

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

          例子

          來實際看一段代碼:

              <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é)點,也就是 nodeType為1的節(jié)點
          2. childNodes 返回所有類型的節(jié)點

          添加節(jié)點 appendappendChild

          node.appendChild[25]

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

          ParentNode.append[26]

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

          例子

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

            <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() 可以追加多個節(jié)點和字符串,而 Node.appendChild() 只能追加一個節(jié)點。

          簡直說, append強大太多了。

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

          document.hidden[27]

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

          Document.visibilityState[28]

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

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

          當此屬性的值改變時, 會遞交 visibilitychange 事件給Document.

          例子

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

                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)聽當前頁面處于隱藏時,去清除定時器或頁面中的動畫, 停止音樂視頻等的播放。

          我還想到一個有意思的

          1. 廣告倒計時

          你離開后,不算倒計時,會不會被罵死

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

          你離開后,停止倒計時

          總結(jié)

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

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

          Function.prototype.call[29]

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

          Function.prototype.apply[30]

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

          Function.prototype.bind[31]

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

          例子

          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ào)用函數(shù)的this指向。

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

          注意點:

          1. bind調(diào)用多次,this指向第一次第一個參數(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的指向不會再變改變,但是參數(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]

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

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

          str.substr(start[, length])

          String.prototype.substring[33]

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

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

          str.substring(indexStart[, indexEnd])

          例子

          提示:

          1. 兩個參數(shù)都沒設(shè)置的時候,效果相同
          2. 第一個參數(shù)是**大于等于0的整數(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 第二個參數(shù)是需要截取的長度
          2. substring 第二個參數(shù)是結(jié)束索引值的
          3. 沒指定參數(shù)或者第一個參數(shù)是大于等于0的整數(shù)時,效果相同
          4. 第一個參數(shù)是負數(shù)或者第二個參數(shù)是負數(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ù)組。一般不可以遍歷對象,如果實現(xiàn)了Symbol.iterator,可以遍歷。如Array,Map,Set,String,TypedArray,arguments 對象等等
          3. 不能獲取原型上的值

          當前時間 Date.now()Performance.now()

          Date.now\(\)[36]

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

          Performance.now[37]

          獲取當前的時間戳的值(自創(chuàng)建上下文以來經(jīng)過的時間),其值是一個精確到毫秒的 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()的基準是 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]

          其包含:主機名,如果 URL 的端口號是非空的,還會跟上一個 ':' ,最后是 URL 的端口號

          location.hostname

          返回域名

          例子

          https與http的默認端口號,是不會被 host包含的,看下面的代碼

          https://developer.mozilla.org:443 的host是 developer.mozilla.org, 因為443是https的默認端口。

                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. 默認端口下, host等于hostname
          2. host額外包含端口號

          事件注冊 onaddEventListener

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

          注冊事件。

          EventTarget.addEventListener[40]

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

          例子

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

             <button id="btn" >點我</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支持多個事件處理程序,并支持事件捕獲。

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

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

          按鍵時間 keypresskeydown

          keypress[42]

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

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

          keydown[43]

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

          例子

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

          image.png

          總結(jié)

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

          異步加載腳本 defer,async

          defer

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

          async

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

          這個一圖勝千文

          image.png

          例子

          四個script標簽,兩個async,兩個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

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

          總結(jié)

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

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


          關(guān)于本文

          作者:云的世界

          https://juejin.cn/post/6982742095375597575


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

             “分享、點贊在看” 支持一波 

          瀏覽 175
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  在线观看视频草女人啊啊 | 久久久久久无码精品人妻一区蜜桃影院 | 成人性爱豆花视频试看 | 人人添人人澡久久婷亚洲AV | 日韩在线观看视频一区二区三区 |