Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国产在线高清一级毛片,久草视频在线免费看,中文字幕一区二区三区在线播放

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          第42節 Element元素節點-Javascrip

          第42節 Element元素節點-Javascript-王唯

          內容是《Web前端開發之Javascript視頻》的課件,請配合大師哥《Javascript》視頻課程學習。

          Element類型用于表示XML或HTML元素,提供了對元素標簽名、子節點及特性的訪問;

          Element類繼承自Node接口;它繼承了Node接口中的所有屬性和方法,比如parentNode、childNode等;同時,它在Node接口的基礎上擴展了自己的屬性和方法;

          Element類型的特征:

          • nodeType值為1;
          • nodeName的值為元素的標簽名;
          • nodeValue的值為null;
          • parentNode可能是Document或Element;
          • 其子節點可能是Element、Text,Comment、ProcessingInstruction、CATASection或EntityReference;
          var mydiv=document.getElementById("mydiv");
          console.log(mydiv.nodeType);  // 1
          console.log(mydiv.nodeName);  // DIV
          console.log(mydiv.nodeValue);  // null
          console.log(mydiv.parentNode);  // <body>
          console.log(mydiv.childNodes);  // NodeList

          Element的屬性:

          id屬性:表示元素的標識符,與全局屬性id對應;

          var mydiv=document.getElementById("mydiv");
          console.log(mydiv.id);
          mydiv.id="yourdiv";
          console.log(mydiv.id);
          var yourdiv=document.getElementById("yourdiv");
          console.log(yourdiv.id);

          tagName屬性:與nodeName屬性一樣,可以返回元素的標簽名,在HTML文檔中返回大寫,在XML中返回原生,因此在使用tagName時,最后使用toLowerCase()轉換;

          var mydiv=document.getElementById("mydiv");
          console.log(mydiv.tagName);  // DIV
          if(mydiv.tagName.toLowerCase()=="div"){
              //...
          }

          一般使用tagName,因為從字義上理解更加清晰;

          Element的子類型HTMLElement:

          HTMLElement類型直接繼承自Element,因此,HTML元素即屬于HTMLElement類也屬于Element類;

          所有HTML元素都由HTMLElement類型或其子類型表示,比如:HTMLDIVElement,就是具體的div元素的類型;

          HTMLElement類型在Element類的基礎上,并添加了一些屬性,這些屬性分別對應于每個HTML元素中都存在的標準特性:id、title、lang、dir、className;

          這些屬性都是可讀可寫的,并且也是動態的;

          <div id="mydiv" name="mydiv" title="DIV" lang="en" dir="ltr" class="divclass">
          // …
          <script>
          var mydiv=document.getElementById("mydiv");
          console.log(mydiv.id);
          console.log(mydiv.title);
          console.log(mydiv.lang);
          console.log(mydiv.dir);
          console.log(mydiv.className);
          mydiv.id="yourdiv";
          mydiv.title="你的DIV";
          mydiv.lang="fr";
          mydiv.dir="rtl";
          mydiv.className="reddiv";
          </script>

          Element特性(屬性):

          每個元素都有若干個特性,這些特性的用途是給出相應元素或其內容的附加信息;DOM為Element對象定義了一些API來獲取或設置這些XML或HTML屬性(特性);

          操作特性主要有三個方法:

          getAttribute()、setAttribute()、removeAttribute();這些方法可以針對任何特性使用,包括那些以HTMLElement類型屬性的形式定義的特性;

          getAttribute(attributeName)方法:

          返回元素上一個指定的特性值,如果指定的特性不存在,則返回null或 "";特性的名稱不區分大小寫;

          如果取得class,需要傳入class,而不是className;

          var mydiv=document.getElementById("mydiv");
          console.log(mydiv.getAttribute("id"));  // mydiv
          console.log(mydiv.getAttribute("class"));  // divclass
          console.log(mydiv.getAttribute("title"));  // null

          也可以取得自定義特性(即不是HTML元素的標準特性),但要注意,根據HTML5的規范,自定義特性應該加上data-前綴以便驗證;

          console.log(mydiv.getAttribute("custom"));  // customvalue
          console.log(mydiv.getAttribute("data-name"));  // wangwei

          任何元素的所有特性,都可以通過DOM元素本身的屬性來訪問,不過,只有公認的(非自定義)特性才會以屬性的形式添加到DOM對象中;但IE可以為自定義特性創建屬性;

          console.log(mydiv.id);
          console.log(mydiv.className);
          console.log(mydiv.myname);  // undefined
          console.log(mydiv.align);  // left,認為align是公認的
          var img=document.getElementById("myimg");
          var imgurl=img.src;
          console.log(img.id==="myimg");
          var f=document.forms[0];
          f.action="https://www.zeronetwork.cn/do.php";
          f.method="POST";

          HTML屬性名不區分大小寫,但Javascript屬性名則大小寫敏感;從HTML屬性名轉換到Javascript屬性名應該采用小寫,但是如果屬性名包含不止一個單詞,則采用小駝峰式,如:defaultCheded和tabIndex;

          有些HTML屬性名在Javascript中是保留字,對于這些屬性,一般的規則是為該屬性名加前綴”html”,如,HTML的for屬性在Javascript中變為htmlFor屬性,class屬性比較特殊,它在Javascript中變成className屬性;

          表示HTML屬性的值通常是字符串,但當屬性為布爾值或數值時,Javascript中對應的屬性也是布爾值或數值,而不是字符串;

          <label id="lbInput" for="txtInput">文本框:</label>
          <input id="txtInput" tabindex="2" type="text" readonly />
          <script>
          var txtInput=document.getElementById("txtInput");
          console.log(txtInput.tabIndex);  // 1
          console.log(txtInput.readOnly);  // true
          var lbInput=document.getElementById("lbInput");
          console.log(lbInput.htmlFor);  // txtInput
          </script>

          style和事件處理程序特性:

          style:在通過getAttribute()訪問時,返回的style特性值中包含的是CSS文本;而通過屬性訪問它會返回一個CSSStyleDeclaration對象(由于style屬性是用于以編程方式訪問元素樣式的對象,因此并沒有直接映射到style特性,有關CSS編程,后面我們會講到);

          事件處理程序特性,類似于onclick等這樣的事件處理程序,當在特性中使用時,onclick中包含的就是JS代碼,使用getAttribute()會返回相應的代碼的字符串,但在訪問onclick屬性時,會返回一個Javascript函數;

          var mydiv=document.getElementById("mydiv");
          console.log(mydiv.getAttribute("style")); // font-size: 14px;color:red;
          console.log(mydiv.style); // CSSStyleDeclaration or CSS2Properties
          console.log(mydiv.getAttribute("onclick"));  // alert('zeronetwork');
          console.log(mydiv.onclick); // function onclick(event)

          setAttribute(name, value)方法:

          設置指定元素上的某個特性值,如果特性已經存在,則更新該值,否則,使用指定的名稱和值添加一個新的特性;

          該接受兩個參數:要設置的特性名和值;

          此方法可以操作HTML特性也可以操作自定義特性;

          var mydiv=document.getElementById("mydiv");
          mydiv.setAttribute("id","outerdiv");
          mydiv.setAttribute("class","outerdivclass");
          mydiv.setAttribute("title","mydiv title");
          mydiv.setAttribute("style","border-bottom:1px solid;color:purple;");
          mydiv.setAttribute("custom","custom value");
          console.log(mydiv.title);  // mydiv title
          console.log(mydiv.custom);  // undefined

          通過該方法設置的特性名會被統一轉換成小寫形式,即“ID”最終會變成“id”;

          mydiv.setAttribute("ID","myID");  // id
          mydiv.setAttribute("CID","customID");  // cid

          布爾特性只要出現在元素上就會被認為是 true,無論它的值是什么;一般來說,應該將 value 設置為空字符串,也有人使用這個屬性的名稱作為值,雖然不會出現什么問題,但不規范的;

          var txtInput=document.getElementById("txtInput");
          txtInput.setAttribute("readonly",true);// 會渲染成readonly="true"
          txtInput.setAttribute("readonly",""); // 渲染成readonly
          console.log(txtInput.readOnly);  // true

          因為所有特性都是屬性,所以直接給屬性賦值可以設置特性的值,但如果添加的是一個自定義的屬性,該屬性不會自動成為元素的特性;

          mydiv.title="mydiv title";
          mydiv.style="border-bottom:1px solid;color:purple;";
          mydiv.custom="custom value";  // html中并沒有渲染custom
          console.log(mydiv.title);  // mydiv title
          console.log(mydiv.custom);  // custom value
          console.log(mydiv.getAttribute("title")); // mydiv title
          console.log(mydiv.getAttribute("custom")); // null

          可以通過setAttribute()方法設置class,但不能通過屬性設置class,因為class是關鍵字,需要className進行屬性設置;

          var mydiv=document.getElementById("mydiv");
          mydiv.setAttribute("class","att_class");
          // mydiv.class="att_class";  // 無效,class是保留字
          mydiv.className="att_class";
          console.log(mydiv.class);  // undefined
          console.log(mydiv.className);  // att_class

          removeAttribute(attrName)方法:

          用于從指定的元素徹底刪除元素的特性;

          此方法不僅會清除特性的值,而且也會從元素中完全刪除特性;

          此方法并不常用,但在序列化DOM元素時,可以通過它來確切地指定要包含哪些特性;

          var mydiv=document.getElementById("mydiv");
          mydiv.removeAttribute("class");
          mydiv.removeAttribute("style");
          mydiv.setAttribute("custom","custom_value");
          mydiv.removeAttribute("custom");
          mydiv.title="mydiv title";
          mydiv.removeAttribute("title");

          hasAttribute(attrName)方法和hasAttributes()方法:

          用于檢測特性是否存在;其中hasAttribute()需要一個特性參數,判斷該元素是否包含有指定的特性,而hasAttributes()檢測的是否有特性,具體是什么特性,則不是它所關心的了;

          var mydiv=document.getElementById("mydiv");
          console.log(mydiv.hasAttribute("title"));
          if(!mydiv.hasAttribute("align"))
              mydiv.setAttribute("align","center");
          console.log(mydiv.hasAttributes());  // true

          當屬性為布爾值時,hasAttribute()方法特別有用,比如HTML表單的disabled屬性,只要判斷它有沒有這個屬性即可,不用管它的值;

          attributes屬性:

          返回該元素所有屬性節點的一個實時集合,該集合是一個NamedNodeMap對象,是一個只讀的類數組對象,只有Element類型擁有;該屬性與NodeList類似,也是一個動態的集合;也可以使用索引方式訪問,并且可以枚舉;

          元素的每個特性都由一個Attr節點表示,Attr對象是一個特殊的Node,不會像普通的Node一樣去使用;Attr的name和value屬性返回該屬性的名字和值;

          每個Attr節點都保存在NamedNodeMap對象中;此節點都有nodeName、nodeValue等屬性,nodeName就是特性的名稱,nodeValue就是特性的值;

          var mydiv=document.getElementById("mydiv");
          console.log(mydiv.attributes);
          console.log(mydiv.attributes[1]);
          console.log(mydiv.attributes.title);
          console.log(mydiv.attributes.custom);
          mydiv.attributes.title="wangwei";  // 無效
          console.log(mydiv.attributes[1].nodeType);  // ATTRIBUTE_NODE
          console.log(mydiv.attributes[1].nodeName);
          console.log(mydiv.attributes[1].nodeValue);

          NamedNodeMap對象:

          表示一個無順序的屬性節點 Attr 對象的集合;其是類數組對象,同時也是動態的;

          屬性和方法:

          length屬性:返回映射(map)中對象的數量;

          getNamedItem(name):返回給定名稱name的屬性節點;

          item(pos):返回位于數字pos位置處的節點;(注:各個瀏覽器會返回不同的順序);

          setNamedItem(node):向列表中添加或替換特性節點;

          removeNamedItem(name):從列表中移除特性為name的節點;與removeAttribute()相同,但其會返回被刪除的特性(Attr)節點;

          可以通過attributes屬性使用方括號直接訪問特性;

          var mydiv=document.getElementById("mydiv");
          console.log(mydiv.attributes);
          console.log(mydiv.attributes.item(1));
          console.log(mydiv.attributes.getNamedItem("name"));
          console.log(mydiv.attributes[1]);
          console.log(mydiv.attributes["name"]);
          mydiv.attributes["id"].nodeValue="newID";
          mydiv.attributes.getNamedItem("name").nodeValue="newName";
          var deleteStyle=mydiv.attributes.removeNamedItem("style");
          console.log(deleteStyle);
          var yourdiv=document.getElementById("yourdiv");
          yourdiv.attributes.setNamedItem(deleteStyle);
          var attr=document.createAttribute("dir");
          attr.nodeValue="ltr";
          mydiv.attributes.setNamedItem(attr);

          使用attributes屬性較麻煩,因此使用getAttribute()、removeAttribute()和removeAttribute()方法比較常用;但在遍歷元素的特性時,attributes屬性比較方便;

          遍歷attributes屬性:

          在需要將DOM結構序列化為XML或HTML字符串時,多數都會涉及遍歷元素特性;

          // 迭代元素的所有特性,構造成name=”value” name=”value”這樣的字符串格式
          var mydiv=document.getElementById("mydiv");
          function outputAttributes(element){
              var pairs=new Array();
              for(var attr in element.attributes){
                  if(element.attributes[attr] instanceof Attr){
                      // console.log(attr + element.attributes[attr]);
                      var attrName=element.attributes[attr].nodeName;
                      var attrValue=element.attributes[attr].nodeValue;
                      // console.log(attrName);
                      pairs.push(attrName + "=\"" + attrValue + "\"");
                  }
              }
              // 或者使用for循環
              // for(var i=0,len=element.attributes.length; i<len; i++){
              //     var attrName=element.attributes[i].nodeName;
              //     var attrValue=element.attributes[i].nodeValue;
              //     // console.log(attrName);
              //     pairs.push(attrName + "=\"" + attrValue + "\"");
              // }
              return pairs.join(" ");
          }
          console.log(outputAttributes(mydiv));

          創建Element元素:

          document.createElement(tagName)方法:用于創建一個由標簽名稱tagName指定的HTML元素,如果用戶代理無法識別tagName,則會生成一個未知 HTML 元素;

          該方法只接受一個參數,即要創建元素的標簽名;此標簽名在HTML中不區分大小寫,在XML(包括XHTML)中,是區分大小寫的;

          在創建新元素的同時,也為新元素設置了ownerDocument屬性;同時還可以操作元素的特性,為它添加子節點,以及執行其他操作;

          新創建的元素,必須添加到文檔樹中,才能顯示出來,可以利用appendChild,insertBefore()或replaceChild()方法;

          var div=document.createElement("div");
          div.innerHTML="<h2>零點程序員</h2>";
          div.id="outerDiv";
          div.className="outerDiv";
          div.setAttribute("style","color:green;");
          console.log(div.ownerDocument);
          document.body.appendChild(div);
          var h3=document.createElement("h3");
          h3.setAttribute("onclick","alert('this is zeronetwork');");
          h3.innerText="zeronetwork";
          div.insertBefore(h3, null);

          Element的子節點:

          元素可以有任意數目的子節點和后代節點,這些子節點可能是元素、文本、注釋處處理指令;但HTML中的空白也會被解析為文本節點;因此在執行某項操作時,要先檢查一下nodeType屬性;

          <!-- 結構 -->
          <ul id="myList">
              <li>HTML</li>
              <li>CSS</li>
              <li>Javascript</li>
          </ul>
          <!-- 或者刪除空白 -->
          <ul id="myList"><li>HTML</li><li>CSS</li><li>Javascript</li></ul>
          // js代碼
          var myList=document.getElementById("myList");
          console.log(myList.childNodes.length);
          for(var i=0,len=myList.childNodes.length; i<len; i++){
              if(myList.childNodes[i].nodeType==Node.ELEMENT_NODE)
                  console.log(myList.childNodes[i].nodeName);
          }
          // 或者
          // for(var n in myList.childNodes){
          //     if(myList.childNodes[n].nodeType && myList.childNodes[n].nodeType==Node.ELEMENT_NODE)
          //         console.log(myList.childNodes[n].nodeName);
          // }

          元素節點也支持getElementsByTagName() 方法,可以通過它獲得某個特定的標簽名的子節點或后代節點;

          var myList=document.getElementById("myList");
          var lis=myList.getElementsByTagName("li");
          console.log(lis);  // dom.html:23 HTMLCollection(3)

          自定義Element的方法:

          Element和HTMLDocument等類型都像String和Array一樣是類,它們不是構造函數,但它們有原型對象,可以自定義方法擴展它;

          Element.prototype.next=function(){
              if(this.nextElementSibling) return this.nextElementSibling;
              var sib=this.nextSibling;
              while(sib && sib.nodeType !==1) sib=sib.nextSibling;
              return sib;
          }
          console.log(document.getElementById("mydiv").next());

          Web前端開發之Javascript-零點程序員-王唯

          、深淺拷貝的區別有哪些?

          要說 js 的深淺拷貝,就不得不提 js 的兩大數據類型:基本數據類型和引用類型。基本數據類型的變量名和值都存儲在棧中,對于引用類型的變量名存儲在棧中,而值存儲在堆中。由于存儲方式不同,所以導致了他們復制的時候方式不同。

          淺拷貝是創建一個新對象,這個對象有著原始對象屬性值的一份精準拷貝。如果屬性是基本類型,拷貝的就是基本類型的值,如果是引用類型,拷貝的就是內存地址,所以如果其中一個對象改變了這個地址,就會影響到另外一個對象。

          深拷貝是將一個對象從內存中完整的拷貝一份出來,從內存堆中存放一個新的對象。這是兩個對象,所以修改其中一個,另外一個不會受影響。

          深淺拷貝主要針對的是引用類型,簡單數據類型不受影響。

          相關筆試題

          var person={
           name:"前端人",
           hobby:['學習','敲代碼','潛水']
          }
          function copy(source){
           var newObj=new Object()
           for(var i in source){
            if(source.hasOwnProperty(i)){
             newObj[i]=source[i]
             }
            }
           return newObj
          }
          var p1=copy(person);
          p1.name="Web Person"
          console.log(person.name)
          console.log(p1.name)
          p1.hobby=["內卷"]
          console.info(person.hobby)
          console.info(p1.hobby)
          /*運行結果:
          前端人
           Web Person
          ["學習", "敲代碼", "潛水"]
          ["內卷"]
          */

          2、js 數據類型有哪些?

          js 數據類型一共有 8 種,分為兩大類:基本類型和引用類型。

          它們的數據類型分別為:

          基本類型:string、number、boolean、null、undefined、symbol、bigint

          引用類型:object

          相關面試題

          // 注意:其他類型與數值進行相加時,其他類型的轉為 number 類型
          console.log( true+1 ) // 2
          console.log( undefined +1 ) // NaN
          
          console.log( null ) //object
          console.log( undefined ) // undefined

          3、延遲加載 js 的方式有哪些?有什么區別呢?

          共有 6 種方式,分別為:

          • async
          • defer
          • js 最后加載
          • 利用 setTimeout
          • 動態創建 DOM 的方式
          • 使用 jQuery 的 getScript 方法

          它們的區別介紹:

          1、async:為 <script>標簽定義了 async 屬性。async 和 html 解析是同步的,不是順次執行 js 腳本,誰先加載完成先執行誰。

          <script  async type="text/javascript" src="demo1.js" ></script>
          <script  async type="text/javascript" src="demo2.js" ></script>

          2、defer 會等到 html 解析完成之后再執行 js 代碼,如果有多個腳本時,會按照順序依次執行腳本。

          <script  defer type="text/javascript" src="demo1.js" ></script>

          3、js 最后加載

          把 js 外部引入的文件放置在頁面的底部,讓 js 最后加載,從而加快頁面加載速度。

          4、利用 setTimeout

          5、動態創建 DOM 的方式

          var element=document.createElement("script");  
          element.src="box.js";  
          document.body.appendChild(element);

          這種方式通過操作動態加載 js 文件,不觸發的時候不加載,減少頁面文件大小,加快加載速度。

          6、使用 jQuery 的 getScript 方法

          $.getScript( "box.js",function(){//回調函數,成功獲取文件后執行的函數  
                console.log("腳本加載完成")  
          });

          相關面試題:

          <!doctype html>
          <html>
           <head>
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <script type="text/javascript" src="box.js"></script>
           </head>
           <body>
            <div id="box"></div>
           </body>
          </html>
          
          //box.js 代碼如下
          console.log( document.getElementById('box') )  // null

          box.js 想正常獲取元素 box ,并進行一系列操作應該如何延遲加載 js 文件呢?

          4、你對作用域的認識有多少?

          作用域通俗地講,就是指一個變量的作用范圍。分為全局作用域和函數作用域。

          全局作用域

          • 頁面打開時被創建,頁面關閉時被銷毀。
          • 編寫在 script 標簽下的變量和函數,作用域為全局,頁面的任意位置都可以訪問
          • 有全局對象 window ,代表瀏覽器窗口,全局作用下的變量和函數作為 window 的屬性和方法

          函數作用域(局部)

          • 函數是被調用時創建的,執行完畢之后銷毀。
          • 函數每調用一次,變量和函數就會重新創建一次,它們之間是相互獨立的
          • 在函數作用域內可以訪問到全局變量或函數,但是在函數外無法訪問函數作用域內的變量
          • 函數作用域內訪問變量,會在自身作用域內尋找,若沒有則會向上一級作用域內查找,一直到全局作用域。

          函數在被調用的時候會先進行預編譯:

          全局作用域預編譯:

          • 創建上下文 GO 對象。
          • 找變量聲明,將變量名作為 GO 對象的屬性名,值為 undefined
          • 找函數式聲明,將值賦予函數體

          函數作用域預編譯:

          • 創建上下文 AO 對象
          • 將形參和實參作為 AO 對象的屬性,賦值為 undefined
          • 實參和形參相統一
          • 在函數體內找函數聲明,將值賦予函數體。

          相關面試題:

          <script type="text/javascript">
           function fn(a,c){
            console.log(a)
            var a=12
            console.log(a)
            console.log(c)
            function a(){ }
            if(false){
             var d=34
            }
            console.log(d)
            console.log(b)
            var b=function(){}
            console.log(b)
            function c(){}
            console.log(c)
           }
           fn(1,2)
          </script>
          // 運行結果:
          /*
          function a(){}
          12
          function c(){}
          undefined
          undefined
          function (){}
          function c(){}
          */

          5、null 和 undefined 的區別。

          null 和 undefined 兩個都表示無的值。

          作者設計 js 的時候,借鑒的 java 語言先設計的 null 。null 使用的時候會被隱式轉化成 0,不容易發現錯誤。

          console.log( number(null) ) //0

          undefined 是為了填補 null 的坑。所以后來又新增了 undefined 。

          console.log( number(undefined) ) //NaN

          6、new 操作符具體做了什么?

          • 創建了一個空對象。
          • 將空對象的原型指向于構造函數的原型。
          • 將空對象作為構造函數的上下文。
          • 對構造函數有返回值的處理判斷。

          實現 new 操作符的方法:

          function create( fn,...args ){
           var obj={}
           Object.setPrototypeOf( obj,fn.prototype )
           var resault=fn.apply(obj,args)
           return (resault instanceof Object) ? result : obj
          }

          7、為什么會有閉包?它解決了什么問題?

          7.1、什么是閉包?

          閉包就是函數嵌套函數,通過函數內的函數訪問變量的規則,實現外部訪問函數內的變量。

          7.2、閉包的特點:

          • 函數嵌套函數。
          • 函數內部可以引用函數外部的參數和變量。
          • 參數和變量不會被垃圾回收機制回收。

          實例3:閉包解決問題

          var liArr=document.getElementsByTagName('li')
          for(var i=0;i<liArr.length;i++){
           (function(i){
            liArr[i].onclick=function(){
             console.log('點擊元素',liArr[i])
            }
           })(i) 
          }

          7.3、閉包優點:

          • 保護變量安全,實現封裝,防止變量聲明沖突和全局污染。
          • 在內存當中維持一個變量,可以做緩存。
          • 匿名函數自執行函數可以減少內存消耗。

          防抖和節流就是閉包的經典應用。

          7.4、閉包缺點:

          • 變量會駐留在內存中,造成內存損耗問題。解決辦法:把閉包函數設置為 null 。
          • 內存泄漏

          8、防抖和節流,你了解多少?

          8.1、什么是防抖函數?

          當持續觸發事件,一定時間內沒有再觸發事件,事件處理函數才會執行一次,如果在設定的時間到來之前又觸發了事件,就會重新計時。

          防抖函數常見的實際應用:使用 echart 的時候,瀏覽器 resize 時,需要重新繪制圖表大小,還有典型的輸入框搜索應用。

          8.2、節流函數是什么?

          當持續觸發事件的時候,保證一段時間內只調用一次事件處理函數,一段時間內,只允許做一件事情。

          防抖和節流主要是用來限制觸發頻率較高的事件,再不影響效果的前提條件下,降低事件觸發頻率,減小瀏覽器或服務器的壓力,提升用戶體驗效果。

          9、數組去重有幾種方法?

          方法1: new set()

          return Array.from(new Set(arr))
          // 或
          return [...new Set(arr)]

          方法2:使用兩次循環

          for(var i=0,len=arr.length;i<len;i++){
           for(var j=i+1,len=arr.length;j<len;j++){
            if( arr[i]===arr[j] ){
             arr.splice(i,1)
             j--;
             len--
            }
           }
          }
          return arr

          方法3:indexOf 實現

          let arr1=[]
          for(var i=0;i<arr.length;i++){
           if( arr1.indexOf(arr[i])===-1 ){
            arr1.push(arr[i])
           }
          }
          return arr1

          方法4:includes 實現

          let arr1=[]
          for(var i=0;i<arr.length;i++){
           if( !arr1.includes(arr[i]) ){
            arr1.push(arr[i])
           }
          }
          return arr1

          方法5:filter 實現

          array.indexOf(item,start) start 表示開始檢索的位置。

          return arr.filter(( item, index )=>{
           return arr.indexOf( item, 0 )==index
          })

          10、call、bind 和 apply 的區別

          三者都是改變函數執行的上下文,即改變 this 指向。

          它們之間的區別為:

          • call 和 apply 會立即執行,bind 返回的是一個函數,需調用后執行。
          • 第二參數是傳入要執行的方法中的參數,call 和 bind 是獨立傳遞參數,apply 是以數組傳遞參數的

          使用場景:
          1、需要改變某個函數的this指向時
          2、當參數較少時可以使用call,參數較多可以使用apply以數組的方式傳遞
          3、當需要重復調用時,可以使用bind新定義一個方法

          11、js 判斷變量是不是數組,你能寫出幾種方法?

          方法1:isArray

          var arr=[1,2,3]
          console.log(Array.isArray(arr))    

          方法2:instanceof

          var arr=[1,2,3]
          console.log( arr instanceof Array )
          console.log( arr instanceof Object )

          該方法不夠嚴謹。

          方法3:prototype

          console.log( Object.prototype.toString.call(arr).indexOf('Array')>-1 )

          方法4:isPrototypeOf

          console.log( Array.prototype.isPrototypeOf( arr ) )

          方法5:constructor

          console.log(arr.constructor.toString().indexOf('Array')>-1 )

          12、slice 是干嘛的? splice 是否會改變原數組?

          slice 是用來截取字符串的,返回一個新數組,但不會影響原數組。

          使用語法:

          arr.slice( start , end )

          截取 arr 數組,從 start 開始到 end 結束,第二個參數是可選參數,沒有時從 start 開始截取到結尾。

          如果 start 參數是負數時,就會從 arr.lengtn + start 開始截取到結束。

          var arr=['a','b','c','d','e']
          console.log( arr.slice(-3) ) // ["c", "d", "e"]
          console.log(arr)  //["a", "b", "c", "d", "e"]

          splice 是一個更強大的方法,可以添加、刪除、替換數組元素,返回的是被刪除元素,它的操作會改變原數組。

          使用語法:

          splice( start, n, new )

          從 start 開始,刪除 n 個元素,然后把 new 添加到 start 元素之后。第三個參數為可選參數

          • n 為 0 且第三個參數不為空時,表示添加新元素到 start 之后。
          • n 不為 0 且第三個參數不為空時,表示把 start 之后的 n 個元素替換成 new 。
          • n 不為 0 且第三個參數為空時,表示刪除 start 后的 n 個元素。
          var arr=['a','b','c','d','e']
          var ar=arr.splice( 1, 1 ,'f','g')
          console.log('ar',ar)    // ["b"]
          console.log('arr',arr) //  ["a", "f", "g", "c", "d", "e"]

          13、==和===有什么不同?

          ==比較的是值,===除了比較值,還比較類型。

          console.log( [1,2]=='1,2'  )       // true
          console.log( [1,2]==='1,2'  )  //false

          valueOf 方法返回 Math 對象的原始值,通常由 javascript 在后臺自動調用,并不顯示的出現在代碼中。

          console.log([1,2].valueOf()) //[1,2]
          console.log('1,2'.valueOf()) //[1,2]
          // 所以
          console.log( [1,2]=='1,2'  )  // true

          不管是字符串和數字比較,還是布爾值和數字比較,都會使用 valueOf 隱式轉換。

          總結:==需要使用 valueOf() 進行隱式轉換,所以性能差。===會避開一些不必要的麻煩。

          14、this 的指向

          大廠筆試題:

          var name='window name'
          var p1={
           name:'p1 name',
           showName:function(){
            console.info(this.name)
           }
          }
          var fn=p1.showName
          fn()
          p1.showName()
          var p2={
           name:'p2 name',
           showName:function(fun){
            fun()
           }
          }
          p2.showName(p1.showName)
          p2.showName=p1.showName
          p2.showName()
          /*
          運行結果:
          window name
           p1 name
           window name
           p2 name
          */

          這是一道關于 this 指向的面試題,接下來我們就說說 this 是如何指向的?

          this 對象是運行時基于函數的執行環境綁定的:

          • 在全局函數中,this 等于 window 。
          • 函數上下文調用,嚴格模式下 this 為 undefined ,非嚴格模式下,this 指向 window 。
          • 當函數被作為某個對象的方法被調用時,this 等于那個對象。如果使用 call apply 改變當前 this 時,將會指向為傳遞過來的那個 this 。
          • 匿名函數的執行環境具有全局性,因此 this 指向 window。
          • 構造函數內的 this 指向創建的實例對象。
          • dom 事件處理函數,this 指向觸發該事件的元素。
          • setTimeout 和 setInterval 中的 this 指向全局變量 window

          15、js 中的繼承有哪些方式呢?

          第 1 種:原型鏈繼承

          function Parent(){
           this.name="前端人"
          }
          Parent.prototype.showName=function(){
           console.log(this.name)
          }
          function Child(){}
           //原型鏈繼承   
          Child.prototype=new Parent()
          var p=new Child()
          console.dir(p.name) //前端人

          特點:

          • 實例的是子類的實例,也是父類的實例。
          • 父類新增原型方法和屬性,子類都能訪問到。
          • 簡單,方便實現

          第 2 種:借用構造函數

          function Animal (name) {
           this.name=name || 'Animal';
           this.sleep=function(){
            console.log(this.name + '正在睡覺!');
           }
          }
          Animal.prototype.eat=function(food) {
           console.log(this.name + '正在吃:' + food);
          };
          function Cat(name){
           Animal.call(this);
           this.name=name || 'Tom';
          }
          // Test Code
          var cat=new Cat();
          console.log(cat.name);
          console.log(cat.sleep());
          console.log(cat instanceof Animal); // false
          console.log(cat instanceof Cat); // true

          特點:

          • 創建子類時,可以向父類傳遞參數。
          • 可以實現多繼承,call 多個父類對象。
          • 解決方法1中,子類實例共享父類引用屬性的問題。

          還有組合式繼承、ES6 的繼承 和 寄生組合繼承等等。每種繼承方式都有各自的特點和缺點。

          16、嚴格模式與非嚴格模式的區別,你了解多少?

          JavaScript 語言是一門弱類型語言,存在許多類型錯誤,因此 ES6 引入了嚴格模式概念。

          如果不加 ‘use strict’ 常規模式下就是屬于非嚴格模式。

          嚴格模式

          在 js 文件頂部添加 ‘use strict’ 就屬于嚴格模式,嚴格模式也可以指定在函數內部。

          <script>
           'use strict'  
           //或者函數內部
           (function(){
            'use strict'
           })()
          </script>

          嚴格模式,是為 js 定義來了一種不同的解析與執行模型,在嚴格模式下,ECMAScipt 3 中一些不解和不確定的行為將得到處理,而且會對不安全的操作會拋出異常。‘use strict’ 會告訴瀏覽器引擎可以切換到嚴格模式執行。

          嚴格模式與非嚴格模式區別

          嚴格模式

          非嚴格模式

          變量必須聲明才能賦值

          變量不進行聲明,可直接賦值

          不能使用 delete 字符刪除變量或對象

          可以使用 delete 刪除

          函數參數變量名不允許重復

          變量名重復,獲取最后最后那個值

          普通函數內的 this 為 undefined

          普通函數內的 this 為 window

          不允許使用八進制

          允許任意進制

          eval 和 arguments 當做關鍵字,不能被賦值和用作變量名

          可以使用 eval 、arguments 作為變量名

          call、apply 傳入 null undefined 保持原樣不被轉為window

          默認轉為 window 對象

          限制對調用棧的檢測能力,訪問 arguments.callee 會拋出異常

          arguments.callee 運行正常

          17、隱式轉化相關面試題

          console.log( '2'>10 ) //false
          console.log( '2'>'10' ) //true
          console.log( 'abc'>'b' ) //false
          console.log( 'abc'>'aab' ) //true
          console.log( undefined==null ) //true
          console.log( NaN==NaN )//false
          console.log( []==0 ) //true
          console.log( ![]==0 ) //true
          console.log( []==[] ) //false
          console.log( {}=={} ) //false
          console.log( {}==!{} ) //false

          18、事件循環機制相關面試題。

          阿里面試題1:

          <script type="text/javascript">
           var p=new Promise(resolve=>{
            console.log(4)
            resolve(5)
           })
           function f1(){
            console.log(1)
           }
           function f2(){
            setTimeout(()=>{
             console.log(2)
            },0)
            f1()
            console.log(3)
            p.then(res=>{
             console.log(res)
            })
           }
           f2()
          </script>
          // 運行結果 4 1 3 5 2
          // 如果已經了解事件運行機制,就可以跳過該問題了

          事件循環機制,event-loop 。包含三部分:調用棧、消息隊列、微任務隊列。

          事件循環開始的時候,會從全局一行一行的執行代碼,遇到函數調用的時候,就會壓入調用棧中,當函數執行完成之后,彈出調用棧。

          // 如:代碼會一行一行執行,函數全部調用完成之后清空調用棧
          function f1(){
           console.log(1)
          }
          function f2(){
           f1()
           console.log(2)
          }
          f2()
          // 執行結果 1 2

          如果遇到 fetch、setInterval、setTimeout 異步操作時,函數調用壓入調用棧時,異步執行內容會被加入消息隊列中,消息隊列中的內容會等到調用棧清空之后才會執行。

          // 如:
          function f1(){
           console.log(1)
          }
          function f2(){
           setTimeout(()=>{
            console.log(2)
           },0)
           f1()
           console.log(3)
          }
          f2()
          // 執行結果 :1 3 2

          遇到 promise、async、await 異步操作時,執行內容會被加入微任務隊列中,會在調用棧清空之后立即執行。

          調用棧加入的微任務隊列會立即執行。

          如
          let p=new Promise(resolve=>{
           console.log('立即執行')
           resolve(1) //在 then 調用中執行
          })

          微任務隊列中內容優先執行,所以比消息隊列中的內容執行得早。

          了解這些知識后,再試一下最前面的那道面試題,應該就沒什么問題了。

          20、前端領域內,你比較擅長什么?

          這個問題就留給讀到最后,能夠堅持學習的人,問問我們自己有什么是我們擅長的?在哪塊領域是我們占據競爭優勢的?

          使用內置JavaScript的對象實例。

          Document 對象

          • 使用 document.write() 輸出文本

          • 使用 document.write() 輸出 HTML

          • 返回文檔中錨的數目

          • 返回文檔中第一個錨的 innerHTML

          • 返回文檔中表單的數目

          • 返回文檔中第一個表單的名字

          • 返回文檔中的圖像數

          • 返回文檔中第一個圖像的ID

          • 返回文檔中的鏈接數

          • 返回文檔中的第一個鏈接的ID

          • 返回文檔中的所有cookies的名稱/值對

          • 返回加載的文檔的服務器域名

          • 返回文檔的最后一次修改時間

          • 返回加載的當前文檔的URL

          • 返回文檔的標題

          • 返回文檔的完整的URL

          • 打開輸出流,向流中輸入文本

          • write() 和 writeln()的不同

          • 用指定的ID彈出一個元素的innerHTML

          • 用指定的Name彈出元素的數量

          • 用指定的tagname彈出元素的數量

          • 更多的Document 對象的例子,在我們的JavaScript 參考手冊。

          Anchor 對象

          • 返回和設置鏈接的charset屬性

          • 返回和設置鏈接的href屬性

          • 返回和設置鏈接的hreflang屬性

          • 返回一個錨的名字

          • 返回當前的文件和鏈接的文檔之間的關系

          • 改變鏈接的target屬性

          • 返回一個鏈接的type屬性的值

          • 更多的Anchor 對象的例子,在我們的JavaScript 參考手冊。

          Area 對象

          • 返回圖像映射某個區域的替代文字

          • 返回圖像映射某個區域的坐標

          • 返回一個區域的href屬性的錨部分

          • 返回的主機名:圖像映射的某個區域的端口

          • 返回圖像映射的某個區域的hostname

          • 返回圖像映射的某個區域的port

          • 返回圖像映射的某個區域的href

          • 返回圖像映射的某個區域的pathname

          • 返回圖像映射的某個區域的protocol

          • 返回一個區域的href屬性的querystring部分

          • 返回圖像映射的某個區域的shape

          • 返回圖像映射的某個區域的target的值

          • 更多的Area 對象的例子,在我們的JavaScript 參考手冊。

          Base 對象

          • 返回頁面上所有相對URL的基URL

          • 返回頁面上所有相對鏈接的基鏈接

          • 更多的Base 對象對象的例子,在我們的JavaScript 參考手冊。

          Button 對象

          • 當點擊完button不可用

          • 返回一個button的name

          • 返回一個button的type

          • 返回一個button的value

          • 返回一個button所屬表的ID

          • 更多Button 對象實例在我們的JavaScript 參考手冊。

          Form 對象

          • 返回一個表單中所有元素的value

          • 返回一個表單acceptCharset屬性的值

          • 返回一個表單action屬性的值

          • 返回表單中的enctype屬性的值

          • 返回一個表單中元素的數量

          • 返回發送表單數據的方法

          • 返回一個表單的name

          • 返回一個表單target屬性的值

          • 重置表單

          • 提交表單

          • 更多Button 對象實例在我們的JavaScript 參考手冊。

          Frame/IFrame 對象

          • 對iframe排版

          • 改變一個包含在iframe中的文檔的背景顏色

          • 返回一個iframe中的frameborder屬性的值

          • 刪除iframe的frameborder

          • 改變iframe的高度和寬度

          • 返回一個iframe中的longdesc屬性的值

          • 返回一個iframe中的marginheight屬性的值

          • 返回一個iframe中的marginwidth屬性的值

          • 返回一個iframe中的name屬性的值

          • 返回和設置一個iframe中的scrolling屬性的值

          • 改變一個iframe的src

          • 更多Frame/IFrame 對象實例在我們的JavaScript 參考手冊。

          Image 對象

          • 對image排版

          • 返回image的替代文本

          • 給image加上border

          • 改變image的高度和寬度

          • 設置image的hspace和vspace屬性

          • 返回image的longdesc屬性的值

          • 創建一個鏈接指向一個低分辨率的image

          • 返回image的name

          • 改變image的src

          • 返回一個客戶端圖像映射的usemap的值

          • 更多Image 對象實例在我們的JavaScript 參考手冊。

          Event 對象

          • 被按下的鍵盤鍵的keycode?

          • 鼠標的坐標?

          • 鼠標相對于屏幕的坐標?

          • shift鍵被按下了嗎?

          • 哪個事件發生了?

          Option and Select 對象

          • 禁用和啟用下拉列表

          • 獲得有下拉列表的表單的ID

          • 獲得下拉列表的選項數量

          • 將下拉列表變成多行列表

          • 在下拉列表中選擇多個選項

          • 彈出下拉列表中被選中的選項

          • 彈出下拉列表中被選中的選項的索引

          • 改變下拉列表中被選中的選項的文本

          • 刪除下拉列表中的選項



          Table, TableHeader, TableRow, TableData 對象

          • 改變表格邊框的寬度

          • 改變表格的cellpadding和cellspacing

          • 指定表格的frame

          • 為表格指定規則

          • 一個行的innerHTML

          • 一個單元格的innerHTML

          • 為表格創建一個標題

          • 刪除表格中的行

          • 添加表格中的行

          • 添加表格行中的單元格

          • 單元格內容水平對齊

          • 單元格內容垂直對齊

          • 對單個單元格的內容水平對齊

          • 對單個單元格的內容垂直對齊

          • 改變單元格的內容

          • 改變行的內容

          如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!


          主站蜘蛛池模板: 国产视频一区二区在线观看| 国产熟女一区二区三区四区五区| 亚洲国产精品一区二区第一页免 | 国产精品成人99一区无码| 99久久精品费精品国产一区二区 | 精品国产一区AV天美传媒| 亚洲一区二区三区乱码A| 麻豆国产在线不卡一区二区| 亚洲一区免费视频| 精品无人区一区二区三区| 国产亚洲福利精品一区| 中文字幕人妻丝袜乱一区三区| 麻豆视传媒一区二区三区| 国产伦精品一区二区三区在线观看 | 国产一区二区在线视频播放| 中文字幕一区在线观看视频| 亚洲第一区视频在线观看| 亚洲天堂一区二区三区四区| 老熟女五十路乱子交尾中出一区| 久久91精品国产一区二区| 美女一区二区三区| 无码人妻一区二区三区免费看| 亚洲AV美女一区二区三区| 日韩在线不卡免费视频一区 | 欧美激情国产精品视频一区二区 | 日本无码一区二区三区白峰美| 精品欧洲av无码一区二区三区| 一区二区三区在线|欧| 一本大道在线无码一区| 国模无码一区二区三区| 好吊妞视频一区二区| 日本一区二区三区在线视频观看免费| 精品国产一区二区二三区在线观看 | 亚洲无线码一区二区三区| 无码少妇一区二区性色AV| 精品一区二区三区四区在线播放| 中文字幕乱码人妻一区二区三区| 韩国精品一区二区三区无码视频 | 怡红院美国分院一区二区| 日韩精品一区二区三区影院| 中文国产成人精品久久一区|