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 久久综合九色欧美综合狠狠,亚洲小说另类,精品久久一区二区

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          HTML&css面試題

          .Doctype作用?標(biāo)準(zhǔn)模式與兼容模式各有什么區(qū)別

          <!DOCTYPE>聲明位于位于HTML文檔中的第一行,處于 <html>標(biāo)簽之前。告知瀏覽器的解析器,用什么文檔標(biāo)準(zhǔn)解析這個(gè)文檔。DOCTYPE不存在或格式不正確會(huì)導(dǎo)致文檔以兼容模式呈現(xiàn)。
          標(biāo)準(zhǔn)模式的排版 和JS運(yùn)作模式都是以該瀏覽器支持的最高標(biāo)準(zhǔn)運(yùn)行。在兼容模式中,頁(yè)面以寬松的向后兼容的方式顯示,模擬老式瀏覽器的行為以防止站點(diǎn)無法工作。

          2.HTML5 為什么只需要寫 <!DOCTYPE HTML>?

          HTML5 不基于 SGML,因此不需要對(duì)DTD進(jìn)行引用,但是需要doctype來規(guī)范瀏覽器的行為(讓瀏覽器按照它們應(yīng)該的方式來運(yùn)行);
          而HTML4.01基于SGML,所以需要對(duì)DTD進(jìn)行引用,才能告知瀏覽器文檔所使用的文檔類型。**

          3.行內(nèi)元素有哪些?塊級(jí)元素有哪些? 空(void)元素有那些?

          首先:CSS規(guī)范規(guī)定,每個(gè)元素都有display屬性,確定該元素的類型,每個(gè)元素都有默認(rèn)的display值,如div的display默認(rèn)值為“block”,則為“塊級(jí)”元素;span默認(rèn)display屬性值為“inline”,是“行內(nèi)”元素
          (1)行內(nèi)元素有:a b span img input select strong(強(qiáng)調(diào)的語(yǔ)氣)
          (2)塊級(jí)元素有:div ul ol li dl dt dd h1 h2 h3 h4…p
          (3)常見的空元素:


          <img><input><link><meta>
          鮮為人知的是:
          <area><base><col><command><embed><keygen><param><source><track><wbr>
          4.頁(yè)面導(dǎo)入樣式時(shí),使用link和@import有什么區(qū)別?
          link屬于XHTML標(biāo)簽,除了加載CSS外,還能用于定義RSS, 定義rel連接屬性等作用;而@import是CSS提供的,只能用于加載CSS;
          頁(yè)面被加載的時(shí),link會(huì)同時(shí)被加載,而@import引用的CSS會(huì)等到頁(yè)面被加載完再加載;
          import是CSS2.1 提出的,只在IE5以上才能被識(shí)別,而link是XHTML標(biāo)簽,無兼容問題;

          5.介紹一下你對(duì)瀏覽器內(nèi)核的理解?

          主要分成兩部分:渲染引擎(layout engineer或Rendering Engine)和JS引擎。
          渲染引擎:負(fù)責(zé)取得網(wǎng)頁(yè)的內(nèi)容(HTML、XML、圖像等等)、整理訊息(例如加入CSS等),以及計(jì)算網(wǎng)頁(yè)的顯示方式,然后會(huì)輸出至顯示器或打印機(jī)。瀏覽器的內(nèi)核的不同對(duì)于網(wǎng)頁(yè)的語(yǔ)法解釋會(huì)有不同,所以渲染的效果也不相同。所有網(wǎng)頁(yè)瀏覽器、電子郵件客戶端以及其它需要編輯、顯示網(wǎng)絡(luò)內(nèi)容的應(yīng)用程序都需要內(nèi)核。
          JS引擎則:解析和執(zhí)行javascript來實(shí)現(xiàn)網(wǎng)頁(yè)的動(dòng)態(tài)效果。
          最開始渲染引擎和JS引擎并沒有區(qū)分的很明確,后來JS引擎越來越獨(dú)立,內(nèi)核就傾向于只指渲染引擎。

          6.常見的瀏覽器內(nèi)核有哪些?

          Trident內(nèi)核:IE,MaxThon,TT,The World,360,搜狗瀏覽器等。[又稱MSHTML]
          Gecko內(nèi)核:Netscape6及以上版本,F(xiàn)F,MozillaSuite/SeaMonkey等
          Presto內(nèi)核:Opera7及以上。 [Opera內(nèi)核原為:Presto,現(xiàn)為:Blink;]
          Webkit內(nèi)核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)]

          7.html5有哪些新特性、移除了那些元素?如何處理HTML5新標(biāo)簽的瀏覽器兼容問題?如何區(qū)分 HTML 和 HTML5?

          • HTML5 現(xiàn)在已經(jīng)不是 SGML 的子集,主要是關(guān)于圖像,位置,存儲(chǔ),多任務(wù)等功能的增加。繪畫 canvas;
            用于媒介回放的 video 和 audio 元素;
            本地離線存儲(chǔ) localStorage 長(zhǎng)期存儲(chǔ)數(shù)據(jù),瀏覽器關(guān)閉后數(shù)據(jù)不丟失;
            sessionStorage 的數(shù)據(jù)在瀏覽器關(guān)閉后自動(dòng)刪除;
            語(yǔ)意化更好的內(nèi)容元素,比如 article、footer、header、nav、section;
            表單控件,calendar、date、time、email、url、search;
            新的技術(shù)webworker, websocket, Geolocation;


          移除的元素:
          純表現(xiàn)的元素:basefont,big,center,font, s,strike,tt,u;
          對(duì)可用性產(chǎn)生負(fù)面影響的元素:frame,frameset,noframes;

          • 支持HTML5新標(biāo)簽:IE8/IE7/IE6支持通過document.createElement方法產(chǎn)生的標(biāo)簽,
            可以利用這一特性讓這些瀏覽器支持HTML5新標(biāo)簽,
            瀏覽器支持新標(biāo)簽后,還需要添加標(biāo)簽?zāi)J(rèn)的樣式。
            當(dāng)然也可以直接使用成熟的框架、比如html5shim;
            <!--[if lt IE 9]>
            <scriptsrc="http://html5shim.googlecode.com/svn/trunk/html5.js"> </script>
            <![endif]-->
          • 如何區(qū)分HTML5: DOCTYPE聲明新增的結(jié)構(gòu)元素功能元素
            H5新特性
            表單 畫布 音視頻 地理定位 媒體查詢 css新特性 離線緩存 本地存儲(chǔ) 拖拽

          8.簡(jiǎn)述一下你對(duì)HTML語(yǔ)義化的理解?

          用正確的標(biāo)簽做正確的事情。
          html語(yǔ)義化讓頁(yè)面的內(nèi)容結(jié)構(gòu)化,結(jié)構(gòu)更清晰,便于對(duì)瀏覽器、搜索引擎解析;
          即使在沒有樣式CSS情況下也以一種文檔格式顯示,并且是容易閱讀的;
          搜索引擎的爬蟲也依賴于HTML標(biāo)記來確定上下文和各個(gè)關(guān)鍵字的權(quán)重,利于SEO;
          使閱讀源代碼的人對(duì)網(wǎng)站更容易將網(wǎng)站分塊,便于閱讀維護(hù)理解。

          9.HTML5的離線儲(chǔ)存怎么使用,工作原理能不能解釋一下?

          在用戶沒有連網(wǎng)時(shí),可以正常訪問站點(diǎn)或應(yīng)用,在用戶與網(wǎng)絡(luò)連接時(shí)更新用戶機(jī)器上的緩存文件。
          原理:HTML5的離線存儲(chǔ)是基于一個(gè)新建的.appcache文件的緩存機(jī)制(不是存儲(chǔ)技術(shù)),通過這個(gè)文件上的解析清單離線存儲(chǔ)資源,這些資源就會(huì)像cookie一樣被存儲(chǔ)了下來。之后當(dāng)網(wǎng)絡(luò)在處于離線狀態(tài)下時(shí),瀏覽器會(huì)通過被離線存儲(chǔ)的數(shù)據(jù)進(jìn)行頁(yè)面展示。
          如何使用
          頁(yè)面頭部像下面一樣加入一個(gè)manifest的屬性;
          在cache.manifest文件的編寫離線存儲(chǔ)的資源;
          CACHE MANIFEST
          #v0.11
          CACHE:
          js/app.js
          css/style.css
          NETWORK:
          resourse/logo.png
          FALLBACK:
          / /offline.html
          在離線狀態(tài)時(shí),操作window.applicationCache進(jìn)行需求實(shí)現(xiàn)。

          10.瀏覽器是怎么對(duì)HTML5的離線儲(chǔ)存資源進(jìn)行管理和加載的呢?

          在線的情況下,瀏覽器發(fā)現(xiàn)html頭部有manifest屬性,它會(huì)請(qǐng)求manifest文件,如果是第一次訪問app,那么瀏覽器就會(huì)根據(jù)manifest文件的內(nèi)容下載相應(yīng)的資源并且進(jìn)行離線存儲(chǔ)。如果已經(jīng)訪問過app并且資源已經(jīng)離線存儲(chǔ)了,那么瀏覽器就會(huì)使用離線的資源加載頁(yè)面,然后瀏覽器會(huì)對(duì)比新的manifest文件與舊的manifest文件,如果文件沒有發(fā)生改變,就不做任何操作,如果文件改變了,那么就會(huì)重新下載文件中的資源并進(jìn)行離線存儲(chǔ)。
          離線的情況下,瀏覽器就直接使用離線存儲(chǔ)的資源。

          11.iframe有那些缺點(diǎn)?

          iframe會(huì)阻塞主頁(yè)面的Onload事件;
          搜索引擎的檢索程序無法解讀這種頁(yè)面,不利于SEO;
          iframe和主頁(yè)面共享連接池,而瀏覽器對(duì)相同域的連接有限制,所以會(huì)影響頁(yè)面的并行加載。
          使用iframe之前需要考慮這兩個(gè)缺點(diǎn)。如果需要使用iframe,最好是通過javascript
          動(dòng)態(tài)給iframe添加src屬性值,這樣可以繞開以上兩個(gè)問題。

          12.Label的作用是什么?是怎么用的?

          label標(biāo)簽來定義表單控制間的關(guān)系,當(dāng)用戶選擇該標(biāo)簽時(shí),瀏覽器會(huì)自動(dòng)將焦點(diǎn)轉(zhuǎn)到和標(biāo)簽相關(guān)的表單控件上。

          <label for="Name">Number:</label>
          <input type=“text“name="Name" id="Name"/>
          <label>Date:<input type="text" name="B"/></label>

          13.如何實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)之間的通信?

          WebSocket、也可以調(diào)用localstorge、cookies等本地存儲(chǔ)方式,還可以使用頁(yè)面的路有參數(shù)傳遞
          localstorge另一個(gè)瀏覽上下文里被添加、修改或刪除時(shí),它都會(huì)觸發(fā)一個(gè)事件,
          我們通過監(jiān)聽事件,控制它的值來進(jìn)行頁(yè)面信息通信;
          14.如何在頁(yè)面上實(shí)現(xiàn)一個(gè)圓形的可點(diǎn)擊區(qū)域?
          map+area或者svg
          border-radius
          純js實(shí)現(xiàn) 需要求一個(gè)點(diǎn)在不在圓上簡(jiǎn)單算法、獲取鼠標(biāo)坐標(biāo)等等

          15.title與h1的區(qū)別、b與strong的區(qū)別、i與em的區(qū)別?

          title屬性沒有明確意義只表示是個(gè)標(biāo)題,H1則表示層次明確的標(biāo)題,對(duì)頁(yè)面信息的抓取也有很大的影響;
          strong是標(biāo)明重點(diǎn)內(nèi)容,有語(yǔ)氣加強(qiáng)的含義,使用閱讀設(shè)備閱讀網(wǎng)絡(luò)時(shí):會(huì)重讀,而是展示強(qiáng)調(diào)內(nèi)容。
          i內(nèi)容展示為斜體,em表示強(qiáng)調(diào)的文本;

          16.data-屬性的作用是什么?

          h5新增的屬性
          可以通過ele.dataset獲取到標(biāo)簽上的data-x的屬性
          返回一個(gè)對(duì)象

          17.常見兼容性問題?

          問題:png24位的圖片在iE6瀏覽器上出現(xiàn)背景,

          解決:解決方案是做成PNG8.

          問題:瀏覽器默認(rèn)的margin和padding不同。

          解決:方案是加一個(gè)全局的*{margin:0;padding:0;}來統(tǒng)一。

          問題:IE6雙邊距bug:塊屬性標(biāo)簽float后,又有橫行的margin情況下,在ie6顯示margin比設(shè)置的大。浮動(dòng)ie產(chǎn)生的雙倍距離 #box{ float:left; width:10px; margin:0 0 0 100px;}這種情況之下IE會(huì)產(chǎn)生20px的距離**

          解決:解決方案是在float的標(biāo)簽樣式控制中加入 ——_display:inline;將其轉(zhuǎn)化為行內(nèi)屬性。(_這個(gè)符號(hào)只有ie6會(huì)識(shí)別)
          漸進(jìn)識(shí)別的方式,從總體中逐漸排除局部。
          首先,巧妙的使用“9”這一標(biāo)記,將IE游覽器從所有情況中分離出來。 接著,再次使用“+”將IE8和IE7、IE6分離開來,這樣IE8已經(jīng)獨(dú)立識(shí)別。
          css

          .bb{ 
             background-color:#f1ee18;/*所有識(shí)別*/ 
            .background-color:#00deff\9; /*IE6、7、8識(shí)別*/ 
            +background-color:#a200ff;/*IE6、7識(shí)別*/ 
            _background-color:#1e0bd1;/*IE6識(shí)別*/ 
            } 
          

          問題:IE下,可以使用獲取常規(guī)屬性的方法來獲取自定義屬性,也可以使用getAttribute()獲取自定義屬性,F(xiàn)irefox下,只能使用getAttribute()獲取自定義屬性.

          解決:解決方法:統(tǒng)一通過getAttribute()獲取自定義屬性.

          問題:IE下,even對(duì)象有x,y屬性,但是沒有pageX,pageY屬性,F(xiàn)irefox下,event對(duì)象有pageX,pageY屬性,但是沒有x,y屬性.

          解決方法:(條件注釋)缺點(diǎn)是在IE瀏覽器下可能會(huì)增加額外的HTTP請(qǐng)求數(shù)。

          問題:Chrome 中文界面下默認(rèn)會(huì)將小于 12px 的文本強(qiáng)制按照 12px 顯示,

          解決:可通過加入 CSS 屬性 -webkit-text-size-adjust: none; 解決.

          問題:超鏈接訪問過后hover樣式就不出現(xiàn)了 被點(diǎn)擊訪問過的超鏈接樣式不在具有hover和active了

          解決:方法是改變CSS屬性的排列順序:L-V-H-A : a:link {} a:visited {} a:hover {} a:active {}

          18.你知道多少種Doctype文檔類型?

          該標(biāo)簽可聲明三種 DTD 類型,分別表示嚴(yán)格版本、過渡版本以及基于框架的 HTML 文檔。
          HTML 4.01 規(guī)定了三種文檔類型:Strict、Transitional 以及 Frameset。
          XHTML 1.0 規(guī)定了三種 XML 文檔類型:Strict、Transitional 以及 Frameset。
          Standards (標(biāo)準(zhǔn))模式(也就是嚴(yán)格呈現(xiàn)模式)用于呈現(xiàn)遵循最新標(biāo)準(zhǔn)的網(wǎng)頁(yè),而 Quirks(包容)模式(也就是松散呈現(xiàn)模式或者兼容模式)用于呈現(xiàn)為傳統(tǒng)瀏覽器而設(shè)計(jì)的網(wǎng)頁(yè)。

          19.HTML與XHTML——二者有什么區(qū)別?

          1)所有的標(biāo)記都必須要有一個(gè)相應(yīng)的結(jié)束標(biāo)記
          2)所有標(biāo)簽的元素和屬性的名字都必須使用小寫
          3)所有的XML標(biāo)記都必須合理嵌套
          4)所有的屬性必須用引號(hào)""括起來
          5)把所有<和&特殊符號(hào)用編碼表示
          6)給所有屬性賦一個(gè)值
          7)不要在注釋內(nèi)容中使“--”
          8)圖片必須有說明文字

          20.<img>的title和alt有什么區(qū)別?

          title是global attributes之一,用于為元素提供附加的advisory information。通常當(dāng)鼠標(biāo)滑動(dòng)到元素上的時(shí)候顯示。
          alt是<img>的特有屬性,是圖片內(nèi)容的等價(jià)描述,用于圖片無法加載時(shí)顯示、讀屏器閱讀圖片。可提圖片高可訪問性,除了純裝飾圖片外都必須設(shè)置有意義的值,搜索引擎會(huì)重點(diǎn)分析。

          21.div+css的布局較table布局有什么優(yōu)點(diǎn)?

          改版的時(shí)候更方便 只要改css文件。
          頁(yè)面加載速度更快、結(jié)構(gòu)化清晰、頁(yè)面顯示簡(jiǎn)潔。
          表現(xiàn)與結(jié)構(gòu)相分離。
          易于優(yōu)化(seo)搜索引擎更友好,排名更容易靠前。

          22.CSS都有哪些選擇器?

          派生選擇器(用HTML標(biāo)簽申明)
          id選擇器(用DOM的ID申明)
          類選擇器(用一個(gè)樣式類名申明)
          屬性選擇器(用DOM的屬性申明,屬于CSS2,IE6不支持,不常用,不知道就算了)
          除了前3種基本選擇器,還有一些擴(kuò)展選擇器,包括
          后代選擇器(利用空格間隔,比如div .a{ })
          群組選擇器(利用逗號(hào)間隔,比如p,div,#a{ })
          那么問題來了,CSS選擇器的優(yōu)先級(jí)是怎么樣定義的?

          基本原則:

          一般而言,選擇器越特殊,它的優(yōu)先級(jí)越高。也就是選擇器指向的越準(zhǔn)確,它的優(yōu)先級(jí)就越高。
          復(fù)雜的計(jì)算方法:
          用1表示派生選擇器的優(yōu)先級(jí)
          用10表示類選擇器的優(yōu)先級(jí)
          用100標(biāo)示ID選擇器的優(yōu)先級(jí)
          div.test1 .span var 優(yōu)先級(jí) 1+10 +10 +1
          span#xxx .songs li 優(yōu)先級(jí)1+100 + 10 + 1
          xxx li 優(yōu)先級(jí) 100 +1
          那么問題來了,看下列代碼,<p>標(biāo)簽內(nèi)的文字是什么顏色的?
          <style>
          .classA{ color:blue;}
          .classB{ color:red;}
          </style>
          <body>
          <p class='classB classA'> 123 </p>
          </body>
          答案:red。與樣式定義在文件中的先后順序有關(guān),即是后面的覆蓋前面的,與在<p class=’classB classA’>中的先后關(guān)系無關(guān)。

          23.行內(nèi)元素和塊級(jí)元素的具體區(qū)別是什么?行內(nèi)元素的padding和margin可設(shè)置嗎?

          塊級(jí)元素(block)特性:
          總是獨(dú)占一行,表現(xiàn)為另起一行開始,而且其后的元素也必須另起一行顯示;
          寬度(width)、高度(height)、內(nèi)邊距(padding)和外邊距(margin)都可控制;
          內(nèi)聯(lián)元素(inline)特性:
          和相鄰的內(nèi)聯(lián)元素在同一行;
          寬度(width)、高度(height)、內(nèi)邊距的top/bottom(padding-top/padding-bottom)和外邊距的top/bottom(margin-top/margin-bottom)都不可改變(也就是padding和margin的left和right是可以設(shè)置的),就是里面文字或圖片的大小。
          那么問題來了,瀏覽器還有默認(rèn)的天生inline-block元素(擁有內(nèi)在尺寸,可設(shè)置高寬,但不會(huì)自動(dòng)換行),有哪些?
          答案:<input> 、<img> 、<button> 、<texterea> 、<label>。

          24.什么是外邊距重疊?重疊的結(jié)果是什么?

          外邊距重疊就是margin-collapse。
          在CSS當(dāng)中,相鄰的兩個(gè)盒子(可能是兄弟關(guān)系也可能是祖先關(guān)系)的外邊距可以結(jié)合成一個(gè)單獨(dú)的外邊距。這種合并外邊距的方式被稱為折疊,并且因而所結(jié)合成的外邊距稱為折疊外邊距。
          折疊結(jié)果遵循下列計(jì)算規(guī)則:
          兩個(gè)相鄰的外邊距都是正數(shù)時(shí),折疊結(jié)果是它們兩者之間較大的值。
          兩個(gè)相鄰的外邊距都是負(fù)數(shù)時(shí),折疊結(jié)果是兩者絕對(duì)值的較大值。
          兩個(gè)外邊距一正一負(fù)時(shí),折疊結(jié)果是兩者的相加的和。

          25.rgba()和opacity的透明效果有什么不同?

          rgba()和opacity都能實(shí)現(xiàn)透明效果,但最大的不同是opacity作用于元素,以及元素內(nèi)的所有內(nèi)容的透明度,
          而rgba()只作用于元素的顏色或其背景色。(設(shè)置rgba透明的元素的子元素不會(huì)繼承透明效果!)

          26.CSS 選擇符有哪些?哪些屬性可以繼承??jī)?yōu)先級(jí)算法如何計(jì)算? CSS3新增偽類有那些?

          *   1.id選擇器( # myid)
              2.類選擇器(.myclassname)
              3.標(biāo)簽選擇器(div, h1, p)
              4.相鄰選擇器(h1 + p)
              5.子選擇器(ul < li)
              6.后代選擇器(li a)
              7.通配符選擇器( * )
              8.屬性選擇器(a[rel = "external"])
              9.偽類選擇器(a: hover, li: nth - child)
          *   可繼承: font-size font-family color, UL LI DL DD DT;
          *   不可繼承 :border padding margin width height ;
          *   優(yōu)先級(jí)就近原則,樣式定義最近者為準(zhǔn);
          *   載入樣式以最后載入的定位為準(zhǔn);

          優(yōu)先級(jí)為:

             !important >  id > class > tag  
             important 比 內(nèi)聯(lián)優(yōu)先級(jí)高

          CSS3新增偽類舉例:

          p:first-of-type 選擇屬于其父元素的首個(gè) <p> 元素的每個(gè) <p> 元素。
          p:last-of-type  選擇屬于其父元素的最后 <p> 元素的每個(gè) <p> 元素。
          p:only-of-type  選擇屬于其父元素唯一的 <p> 元素的每個(gè) <p> 元素。
          p:only-child    選擇屬于其父元素的唯一子元素的每個(gè) <p> 元素。
          p:nth-child(2)  選擇屬于其父元素的第二個(gè)子元素的每個(gè) <p> 元素。
          :enabled、:disabled 控制表單控件的禁用狀態(tài)。
          :checked,單選框或復(fù)選框被選中。

          27.如何居中div,如何居中一個(gè)浮動(dòng)元素?

          給div設(shè)置一個(gè)寬度,然后添加margin:0 auto屬性

          div{

          width:200px;
          margin:0 auto;

          }

          居中一個(gè)浮動(dòng)元素

            確定容器的寬高 寬500 高 300 的層
            設(shè)置層的外邊距
          
          

          .div {
          Width:500px ; height:300px;//高度可以不設(shè)
          Margin: -150px 0 0 -250px;
          position:relative;相對(duì)定位
          background-color:pink;//方便看效果
          left:50%;
          top:50%;
          }

          28.瀏覽器的內(nèi)核分別是什么?經(jīng)常遇到的瀏覽器的兼容性有哪些?原因,解決方法是什么,常用hack的技巧 ?

          *  IE瀏覽器的內(nèi)核Trident、 Mozilla的Gecko、google的WebKit、Opera內(nèi)核Presto;
          *  png24為的圖片在iE6瀏覽器上出現(xiàn)背景,解決方案是做成PNG8.
          *  瀏覽器默認(rèn)的margin和padding不同。解決方案是加一個(gè)全局的*{margin:0;padding:0;}來統(tǒng)一。
          *  IE6雙邊距bug:塊屬性標(biāo)簽float后,又有橫行的margin情況下,在ie6顯示margin比設(shè)置的大。 
            浮動(dòng)ie產(chǎn)生的雙倍距離 #box{ float:left; width:10px; margin:0 0 0 100px;} 
           這種情況之下IE會(huì)產(chǎn)生20px的距離,解決方案是在float的標(biāo)簽樣式控制中加入 ——_display:inline;將其轉(zhuǎn)化為行內(nèi)屬性。(_這個(gè)符號(hào)只有ie6會(huì)識(shí)別)
            漸進(jìn)識(shí)別的方式,從總體中逐漸排除局部。 
            首先,巧妙的使用“\9”這一標(biāo)記,將IE游覽器從所有情況中分離出來。 
            接著,再次使用“+”將IE8和IE7、IE6分離開來,這樣IE8已經(jīng)獨(dú)立識(shí)別。
          
          

          css

            .bb{
             background-color:#f1ee18;/*所有識(shí)別*/
            .background-color:#00deff\9; /*IE6、7、8識(shí)別*/
            +background-color:#a200ff;/*IE6、7識(shí)別*/
            _background-color:#1e0bd1;/*IE6識(shí)別*/
            }
          
          
          *  IE下,可以使用獲取常規(guī)屬性的方法來獲取自定義屬性,
             也可以使用getAttribute()獲取自定義屬性;
             Firefox下,只能使用getAttribute()獲取自定義屬性. 
             解決方法:統(tǒng)一通過getAttribute()獲取自定義屬性.
          *  IE下,even對(duì)象有x,y屬性,但是沒有pageX,pageY屬性; 
            Firefox下,event對(duì)象有pageX,pageY屬性,但是沒有x,y屬性.
          * (條件注釋)缺點(diǎn)是在IE瀏覽器下可能會(huì)增加額外的HTTP請(qǐng)求數(shù)。
          *  Chrome 中文界面下默認(rèn)會(huì)將小于 12px 的文本強(qiáng)制按照 12px 顯示, 可通過加入 CSS 屬性 -webkit-text-size-adjust: none; 解決.
          超鏈接訪問過后hover樣式就不出現(xiàn)了 被點(diǎn)擊訪問過的超鏈接樣式不在具有hover和active了解決方法是改變CSS屬性的排列順序:
          L-V-H-A :  a:link {} a:visited {} a:hover {} a:active {}
          

          29.css優(yōu)先級(jí)算法如何計(jì)算?

          !important > id > class > 標(biāo)簽
          !important 比 內(nèi)聯(lián)優(yōu)先級(jí)高

          • 優(yōu)先級(jí)就近原則,樣式定義最近者為準(zhǔn);
          • 以最后載入的樣式為準(zhǔn);

          30.哪些css屬性可以繼承?

          可繼承: font-size font-family color, ul li dl dd dt;
          不可繼承 :border padding margin width height ;

          DOM

          講 DOM 先從 HTML 講起,講 HTML 先從 XML 講起。XML 是一種可擴(kuò)展的標(biāo)記語(yǔ)言,所謂可擴(kuò)展就是它可以描述任何結(jié)構(gòu)化的數(shù)據(jù),它是一棵樹!

          1.documen.write和 innerHTML的區(qū)別

          document.write只能重繪整個(gè)頁(yè)面
          innerHTML可以重繪頁(yè)面的一部分

          2.DOM操作——怎樣添加、移除、移動(dòng)、復(fù)制、創(chuàng)建和查找節(jié)點(diǎn)?

          1)創(chuàng)建新節(jié)點(diǎn)

          createDocumentFragment() //創(chuàng)建一個(gè)DOM片段
          createElement() //創(chuàng)建一個(gè)具體的元素
          createTextNode() //創(chuàng)建一個(gè)文本節(jié)點(diǎn)

          2)添加、移除、替換、插入

          appendChild()
          removeChild()
          replaceChild()
          insertBefore() //在已有的子節(jié)點(diǎn)前插入一個(gè)新的子節(jié)點(diǎn)

          3)查找

          getElementsByTagName() //通過標(biāo)簽名稱
          getElementsByName() //通過元素的Name屬性的值(IE容錯(cuò)能力較強(qiáng),會(huì)得到一個(gè)數(shù)組,其中包括id等于name值的)
          getElementById() //通過元素Id,唯一性

          3.attribute和property的區(qū)別是什么?

          attribute是dom元素在文檔中作為html標(biāo)簽擁有的屬性;
          property就是dom元素在js中作為對(duì)象擁有的屬性。
          所以:
          對(duì)于html的標(biāo)準(zhǔn)屬性來說,attribute和property是同步的,是會(huì)自動(dòng)更新的,
          但是對(duì)于自定義的屬性來說,他們是不同步的,

          4.src和href的區(qū)別

          src用于替換當(dāng)前元素,href用于在當(dāng)前文檔和引用資源之間確立聯(lián)系。
          src是source的縮寫,指向外部資源的位置,指向的內(nèi)容將會(huì)嵌入到文檔中當(dāng)前標(biāo)簽所在位置;在請(qǐng)求src資源時(shí)會(huì)將其指向的資源下載并應(yīng)用到文檔內(nèi),當(dāng)瀏覽器解析到該元素時(shí),會(huì)暫停其他資源的下載和處理,直到將該資源加載、編譯、執(zhí)行完畢,圖片和框架等元素也如此,類似于將所指向資源嵌入當(dāng)前標(biāo)簽內(nèi)。這也是為什么將js腳本放在底部而不是頭部。
          Src source,指向外部資源的位置,如果我們添加<script src ="js.js"></script>瀏覽器會(huì)暫停其他資源的下載和處理,直到該資源加載,編譯,執(zhí)行完畢(圖片和框架也是如此),這也就是為什么js腳本要放在底部。
          src用于替換當(dāng)前元素,href用于在當(dāng)前文檔和引入資源之間建立聯(lián)系。

          存儲(chǔ)

          cookie

          cookie 本身不是用來做服務(wù)器端存儲(chǔ)的(計(jì)算機(jī)領(lǐng)域有很多這種“狗拿耗子”的例子,例如 CSS 中的 float),它是設(shè)計(jì)用來在服務(wù)器和客戶端進(jìn)行信息傳遞的,因此我們的每個(gè) HTTP 請(qǐng)求都帶著 cookie。但是 cookie 也具備瀏覽器端存儲(chǔ)的能力(例如記住用戶名和密碼),因此就被開發(fā)者用上了。
          使用起來也非常簡(jiǎn)單,document.cookie = ....即可。
          但是 cookie 有它致命的缺點(diǎn):
          存儲(chǔ)量太小,只有 4KB
          所有 HTTP 請(qǐng)求都帶著,會(huì)影響獲取資源的效率
          API 簡(jiǎn)單,需要封裝才能用

          locationStorage 和 sessionStorage

          后來,HTML5 標(biāo)準(zhǔn)就帶來了sessionStorage和localStorage,先拿localStorage來說,它是專門為了瀏覽器端緩存而設(shè)計(jì)的。

          其優(yōu)點(diǎn)有:

          存儲(chǔ)量增大到 5MB
          不會(huì)帶到 HTTP 請(qǐng)求中
          API 適用于數(shù)據(jù)存儲(chǔ) localStorage.setItem(key, value) localStorage.getItem(key)
          sessionStorage的區(qū)別就在于它是根據(jù) session 過去時(shí)間而實(shí)現(xiàn),而localStorage會(huì)永久有效,應(yīng)用場(chǎng)景不同。例如,一些需要及時(shí)失效的重要信息放在sessionStorage中,一些不重要但是不經(jīng)常設(shè)置的信息,放在localStorage中。

          對(duì)WEB標(biāo)準(zhǔn)以及W3C的理解與認(rèn)識(shí)

          標(biāo)簽閉合、標(biāo)簽小寫、不亂嵌套、提高搜索機(jī)器人搜索幾率、使用外 鏈css和js腳本、結(jié)構(gòu)行為表現(xiàn)的分離、文件下載與頁(yè)面速度更快、內(nèi)容能被更多的用戶所訪問、內(nèi)容能被更廣泛的設(shè)備所訪問、更少的代碼和組件,容易維 護(hù)、改版方便,不需要變動(dòng)頁(yè)面內(nèi)容、提供打印版本而不需要復(fù)制內(nèi)容、提高網(wǎng)站易用性;

          答題

          1、什么是防抖和節(jié)流?有什么區(qū)別?如何實(shí)現(xiàn)?

          參考答案
          

          防抖

          觸發(fā)高頻事件后n秒內(nèi)函數(shù)只會(huì)執(zhí)行一次,如果n秒內(nèi)高頻事件再次被觸發(fā),則重新計(jì)算時(shí)間

          • 思路:

          每次觸發(fā)事件時(shí)都取消之前的延時(shí)調(diào)用方法

          function debounce(fn) {
                let timeout = null; // 創(chuàng)建一個(gè)標(biāo)記用來存放定時(shí)器的返回值
                return function () {
                  clearTimeout(timeout); // 每當(dāng)用戶輸入的時(shí)候把前一個(gè) setTimeout clear 掉
                  timeout = setTimeout(() => { // 然后又創(chuàng)建一個(gè)新的 setTimeout, 這樣就能保證輸入字符后的 interval 間隔內(nèi)如果還有字符輸入的話,就不會(huì)執(zhí)行 fn 函數(shù)
                    fn.apply(this, arguments);
                  }, 500);
                };
              }
              function sayHi() {
                console.log('防抖成功');
              }
          
              var inp = document.getElementById('inp');
              inp.addEventListener('input', debounce(sayHi)); // 防抖
          

          節(jié)流

          高頻事件觸發(fā),但在n秒內(nèi)只會(huì)執(zhí)行一次,所以節(jié)流會(huì)稀釋函數(shù)的執(zhí)行頻率

          • 思路:

          每次觸發(fā)事件時(shí)都判斷當(dāng)前是否有等待執(zhí)行的延時(shí)函數(shù)

          function throttle(fn) {
                let canRun = true; // 通過閉包保存一個(gè)標(biāo)記
                return function () {
                  if (!canRun) return; // 在函數(shù)開頭判斷標(biāo)記是否為true,不為true則return
                  canRun = false; // 立即設(shè)置為false
                  setTimeout(() => { // 將外部傳入的函數(shù)的執(zhí)行放在setTimeout中
                    fn.apply(this, arguments);
                    // 最后在setTimeout執(zhí)行完畢后再把標(biāo)記設(shè)置為true(關(guān)鍵)表示可以執(zhí)行下一次循環(huán)了。當(dāng)定時(shí)器沒有執(zhí)行的時(shí)候標(biāo)記永遠(yuǎn)是false,在開頭被return掉
                    canRun = true;
                  }, 500);
                };
              }
              function sayHi(e) {
                console.log(e.target.innerWidth, e.target.innerHeight);
              }
              window.addEventListener('resize', throttle(sayHi));
          

          2、 get請(qǐng)求傳參長(zhǎng)度的誤區(qū)、get和post請(qǐng)求在緩存方面的區(qū)別

          誤區(qū):我們經(jīng)常說get請(qǐng)求參數(shù)的大小存在限制,而post請(qǐng)求的參數(shù)大小是無限制的。

          參考答案

          實(shí)際上HTTP 協(xié)議從未規(guī)定 GET/POST 的請(qǐng)求長(zhǎng)度限制是多少。對(duì)get請(qǐng)求參數(shù)的限制是來源與瀏覽器或web服務(wù)器,瀏覽器或web服務(wù)器限制了url的長(zhǎng)度。為了明確這個(gè)概念,我們必須再次強(qiáng)調(diào)下面幾點(diǎn):

          • HTTP 協(xié)議 未規(guī)定 GET 和POST的長(zhǎng)度限制
          • GET的最大長(zhǎng)度顯示是因?yàn)?瀏覽器和 web服務(wù)器限制了 URI的長(zhǎng)度
          • 不同的瀏覽器和WEB服務(wù)器,限制的最大長(zhǎng)度不一樣
          • 要支持IE,則最大長(zhǎng)度為2083byte,若只支持Chrome,則最大長(zhǎng)度 8182byte

          補(bǔ)充補(bǔ)充一個(gè)get和post在緩存方面的區(qū)別:

          • get請(qǐng)求類似于查找的過程,用戶獲取數(shù)據(jù),可以不用每次都與數(shù)據(jù)庫(kù)連接,所以可以使用緩存。
          • post不同,post做的一般是修改和刪除的工作,所以必須與數(shù)據(jù)庫(kù)交互,所以不能使用緩存。因此get請(qǐng)求適合于請(qǐng)求緩存。

          3、模塊化發(fā)展歷程

          可從IIFE、AMD、CMD、CommonJS、UMD、webpack(require.ensure)、ES Module、<script type="module"> 這幾個(gè)角度考慮。

          參考答案
          

          模塊化主要是用來抽離公共代碼,隔離作用域,避免變量沖突等。

          IIFE:使用自執(zhí)行函數(shù)來編寫模塊化,特點(diǎn):在一個(gè)單獨(dú)的函數(shù)作用域中執(zhí)行代碼,避免變量沖突

          (function(){
            return {
              data:[]
            }
          })()
          

          AMD:使用requireJS 來編寫模塊化,特點(diǎn):依賴必須提前聲明好

          define('./index.js',function(code){
              // code 就是index.js 返回的內(nèi)容
          })
          

          CMD:使用seaJS 來編寫模塊化,特點(diǎn):支持動(dòng)態(tài)引入依賴文件

          define(function(require, exports, module) {  
            var indexCode = require('./index.js');
          })
          

          CommonJS:nodejs 中自帶的模塊化。

          var fs = require('fs');
          

          UMD:兼容AMD,CommonJS 模塊化語(yǔ)法。

          webpack(require.ensure):webpack 2.x 版本中的代碼分割。

          ES Modules:ES6 引入的模塊化,支持import 來引入另一個(gè) js 。

          import a from 'a';
          

          4、npm 模塊安裝機(jī)制,為什么輸入 npm install 就可以自動(dòng)安裝對(duì)應(yīng)的模塊?

          參考答案
          

          1. npm 模塊安裝機(jī)制:

          • 發(fā)出npm install命令
          • 查詢node_modules目錄之中是否已經(jīng)存在指定模塊
            • npm 向 registry 查詢模塊壓縮包的網(wǎng)址
            • 下載壓縮包,存放在根目錄下的.npm目錄里
            • 解壓壓縮包到當(dāng)前項(xiàng)目的node_modules目錄
            • 若存在,不再重新安裝
            • 若不存在

          2. npm 實(shí)現(xiàn)原理

          輸入 npm install 命令并敲下回車后,會(huì)經(jīng)歷如下幾個(gè)階段(以 npm 5.5.1 為例):

          1. 執(zhí)行工程自身 preinstall
            當(dāng)前 npm 工程如果定義了 preinstall 鉤子此時(shí)會(huì)被執(zhí)行。
          2. 確定首層依賴模塊
            首先需要做的是確定工程中的首層依賴,也就是 dependencies 和 devDependencies 屬性中直接指定的模塊(假設(shè)此時(shí)沒有添加 npm install 參數(shù))。
            工程本身是整棵依賴樹的根節(jié)點(diǎn),每個(gè)首層依賴模塊都是根節(jié)點(diǎn)下面的一棵子樹,npm 會(huì)開啟多進(jìn)程從每個(gè)首層依賴模塊開始逐步尋找更深層級(jí)的節(jié)點(diǎn)。
          3. 獲取模塊
            獲取模塊是一個(gè)遞歸的過程,分為以下幾步:
          • 獲取模塊信息。在下載一個(gè)模塊之前,首先要確定其版本,這是因?yàn)?package.json 中往往是 semantic version(semver,語(yǔ)義化版本)。此時(shí)如果版本描述文件(npm-shrinkwrap.json 或 package-lock.json)中有該模塊信息直接拿即可,如果沒有則從倉(cāng)庫(kù)獲取。如 packaeg.json 中某個(gè)包的版本是 ^1.1.0,npm 就會(huì)去倉(cāng)庫(kù)中獲取符合 1.x.x 形式的最新版本。
          • 獲取模塊實(shí)體。上一步會(huì)獲取到模塊的壓縮包地址(resolved 字段),npm 會(huì)用此地址檢查本地緩存,緩存中有就直接拿,如果沒有則從倉(cāng)庫(kù)下載。
          • 查找該模塊依賴,如果有依賴則回到第1步,如果沒有則停止。
        1. 模塊扁平化(dedupe)
          上一步獲取到的是一棵完整的依賴樹,其中可能包含大量重復(fù)模塊。比如 A 模塊依賴于 loadsh,B 模塊同樣依賴于 lodash。在 npm3 以前會(huì)嚴(yán)格按照依賴樹的結(jié)構(gòu)進(jìn)行安裝,因此會(huì)造成模塊冗余。
          從 npm3 開始默認(rèn)加入了一個(gè) dedupe 的過程。它會(huì)遍歷所有節(jié)點(diǎn),逐個(gè)將模塊放在根節(jié)點(diǎn)下面,也就是 node-modules 的第一層。當(dāng)發(fā)現(xiàn)有
          重復(fù)模塊時(shí),則將其丟棄。
          這里需要對(duì)
          重復(fù)模塊進(jìn)行一個(gè)定義,它指的是模塊名相同semver 兼容。每個(gè) semver 都對(duì)應(yīng)一段版本允許范圍,如果兩個(gè)模塊的版本允許范圍存在交集,那么就可以得到一個(gè)兼容版本,而不必版本號(hào)完全一致,這可以使更多冗余模塊在 dedupe 過程中被去掉。
          比如 node-modules 下 foo 模塊依賴 lodash@^1.0.0,bar 模塊依賴 lodash@^1.1.0,則
          ^1.1.0 為兼容版本。
          而當(dāng) foo 依賴 lodash@^2.0.0,bar 依賴 lodash@^1.1.0,則依據(jù) semver 的規(guī)則,二者不存在兼容版本。會(huì)將一個(gè)版本放在 node_modules 中,另一個(gè)仍保留在依賴樹里。
          舉個(gè)例子,假設(shè)一個(gè)依賴樹原本是這樣:
          node_modules -- foo ---- lodash@version1
          -- bar ---- lodash@version2
          假設(shè) version1 和 version2 是兼容版本,則經(jīng)過 dedupe 會(huì)成為下面的形式:
          node_modules -- foo
          -- bar
          -- lodash(保留的版本為兼容版本)
          假設(shè) version1 和 version2 為非兼容版本,則后面的版本保留在依賴樹中:
          node_modules -- foo -- lodash@version1
          -- bar ---- lodash@version2
        2. 安裝模塊
          這一步將會(huì)更新工程中的 node_modules,并執(zhí)行模塊中的生命周期函數(shù)(按照 preinstall、install、postinstall 的順序)。
        3. 執(zhí)行工程自身生命周期
          當(dāng)前 npm 工程如果定義了鉤子此時(shí)會(huì)被執(zhí)行(按照 install、postinstall、prepublish、prepare 的順序)。
          最后一步是生成或更新版本描述文件,npm install 過程完成。
        4. 5、ES5的繼承和ES6的繼承有什么區(qū)別?

          參考答案
          

          ES5的繼承時(shí)通過prototype或構(gòu)造函數(shù)機(jī)制來實(shí)現(xiàn)。ES5的繼承實(shí)質(zhì)上是先創(chuàng)建子類的實(shí)例對(duì)象,然后再將父類的方法添加到this上(Parent.apply(this))。

          ES6的繼承機(jī)制完全不同,實(shí)質(zhì)上是先創(chuàng)建父類的實(shí)例對(duì)象this(所以必須先調(diào)用父類的super()方法),然后再用子類的構(gòu)造函數(shù)修改this

          具體的:ES6通過class關(guān)鍵字定義類,里面有構(gòu)造方法,類之間通過extends關(guān)鍵字實(shí)現(xiàn)繼承。子類必須在constructor方法中調(diào)用super方法,否則新建實(shí)例報(bào)錯(cuò)。因?yàn)樽宇悰]有自己的this對(duì)象,而是繼承了父類的this對(duì)象,然后對(duì)其進(jìn)行加工。如果不調(diào)用super方法,子類得不到this對(duì)象。

          ps:super關(guān)鍵字指代父類的實(shí)例,即父類的this對(duì)象。在子類構(gòu)造函數(shù)中,調(diào)用super后,才可使用this關(guān)鍵字,否則報(bào)錯(cuò)。

          6、setTimeout、Promise、Async/Await 的區(qū)別

          參考答案

          7、定時(shí)器的執(zhí)行順序或機(jī)制?

          參考答案
          

          **因?yàn)閖s是單線程的,瀏覽器遇到setTimeout或者setInterval會(huì)先執(zhí)行完當(dāng)前的代碼塊,在此之前會(huì)把定時(shí)器推入瀏覽器的待執(zhí)行事件隊(duì)列里面,等到瀏覽器執(zhí)行完當(dāng)前代碼之后會(huì)看一下事件隊(duì)列里面有沒有任務(wù),有的話才執(zhí)行定時(shí)器的代碼。**所以即使把定時(shí)器的時(shí)間設(shè)置為0還是會(huì)先執(zhí)行當(dāng)前的一些代碼。

          function test(){
              var aa = 0;
              var testSet = setInterval(function(){
                  aa++;
                  console.log(123);
                  if(aa<10){
                      clearInterval(testSet);
                  }
              },20);
            var testSet1 = setTimeout(function(){
              console.log(321)
            },1000);
            for(var i=0;i<10;i++){
              console.log('test');
            }
          }
          test()
          

          輸出結(jié)果:

          test //10次
          undefined
          123
          321
          

          8、['1','2','3'].map(parseInt) 輸出什么,為什么?

          參考答案
          

          輸出:[1, NaN, NaN]

          • 首先讓我們回顧一下,map函數(shù)的第一個(gè)參數(shù)callback:

          var new_array = arr.map(function callback(currentValue[, index[, array]]) { // Return element for new_array }[, thisArg])這個(gè)callback一共可以接收三個(gè)參數(shù),其中第一個(gè)參數(shù)代表當(dāng)前被處理的元素,而第二個(gè)參數(shù)代表該元素的索引。

          • 而parseInt則是用來解析字符串的,使字符串成為指定基數(shù)的整數(shù)。parseInt(string, radix)接收兩個(gè)參數(shù),第一個(gè)表示被處理的值(字符串),第二個(gè)表示為解析時(shí)的基數(shù)。
          • 了解這兩個(gè)函數(shù)后,我們可以模擬一下運(yùn)行情況
          1. parseInt('1', 0) //radix為0時(shí),且string參數(shù)不以“0x”和“0”開頭時(shí),按照10為基數(shù)處理。這個(gè)時(shí)候返回1
          2. parseInt('2', 1) //基數(shù)為1(1進(jìn)制)表示的數(shù)中,最大值小于2,所以無法解析,返回NaN
          3. parseInt('3', 2) //基數(shù)為2(2進(jìn)制)表示的數(shù)中,最大值小于3,所以無法解析,返回NaN
          • map函數(shù)返回的是一個(gè)數(shù)組,所以最后結(jié)果為[1, NaN, NaN]

          9、Doctype作用? 嚴(yán)格模式與混雜模式如何區(qū)分?它們有何意義?

          參考答案
          

          Doctype聲明于文檔最前面,告訴瀏覽器以何種方式來渲染頁(yè)面,這里有兩種模式,嚴(yán)格模式和混雜模式。

          • 嚴(yán)格模式的排版和 JS 運(yùn)作模式是 以該瀏覽器支持的最高標(biāo)準(zhǔn)運(yùn)行。
          • 混雜模式,向后兼容,模擬老式瀏覽器,防止瀏覽器無法兼容頁(yè)面。

          10、fetch發(fā)送2次請(qǐng)求的原因

          參考答案
          

          fetch發(fā)送post請(qǐng)求的時(shí)候,總是發(fā)送2次,第一次狀態(tài)碼是204,第二次才成功?

          原因很簡(jiǎn)單,因?yàn)槟阌胒etch的post請(qǐng)求的時(shí)候,導(dǎo)致fetch 第一次發(fā)送了一個(gè)Options請(qǐng)求,詢問服務(wù)器是否支持修改的請(qǐng)求頭,如果服務(wù)器支持,則在第二次中發(fā)送真正的請(qǐng)求。


          • location.href-- 返回或設(shè)置當(dāng)前文檔的URL
          • location.search -- 返回URL中的查詢字符串部分。例如 http://www.dreamdu.com/dreamd... 返回包括(?)后面的內(nèi)容?id=5&name=dreamdu
          • location.hash -- 返回URL#后面的內(nèi)容,如果沒有#,返回空 location.host -- 返回URL中的域名部分,例如http://www.dreamdu.com
          • location.hostname -- 返回URL中的主域名部分,例如http://dreamdu.com
          • location.pathname -- 返回URL的域名后的部分。例如 http://www.dreamdu.com/xhtml/ 返回/xhtml/
          • location.port -- 返回URL中的端口部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回8080
          • location.protocol -- 返回URL中的協(xié)議部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回(//)前面的內(nèi)容http:
          • location.assign -- 設(shè)置當(dāng)前文檔的URL
          • location.replace() -- 設(shè)置當(dāng)前文檔的URL,并且在history對(duì)象的地址列表中移除這個(gè)URL location.replace(url);
          • location.reload() -- 重載當(dāng)前頁(yè)面

          history對(duì)象

          • history.go() -- 前進(jìn)或后退指定的頁(yè)面數(shù)
          • history.go(num); history.back() -- 后退一頁(yè)
          • history.forward() -- 前進(jìn)一頁(yè)

          Navigator對(duì)象

          • navigator.userAgent -- 返回用戶代理頭的字符串表示(就是包括瀏覽器版本信息等的字符串)
          • navigator.cookieEnabled -- 返回瀏覽器是否支持(啟用)cookie

          6、Cookie、sessionStorage、localStorage的區(qū)別

          參考答案
          

          共同點(diǎn):都是保存在瀏覽器端,并且是同源的

          • Cookie:cookie數(shù)據(jù)始終在同源的http請(qǐng)求中攜帶(即使不需要),即cookie在瀏覽器和服務(wù)器間來回傳遞。而sessionStorage和localStorage不會(huì)自動(dòng)把數(shù)據(jù)發(fā)給服務(wù)器,僅在本地保存。cookie數(shù)據(jù)還有路徑(path)的概念,可以限制cookie只屬于某個(gè)路徑下,存儲(chǔ)的大小很小只有4K左右。(key:可以在瀏覽器和服務(wù)器端來回傳遞,存儲(chǔ)容量小,只有大約4K左右)
          • sessionStorage:僅在當(dāng)前瀏覽器窗口關(guān)閉前有效,自然也就不可能持久保持,localStorage:始終有效,窗口或?yàn)g覽器關(guān)閉也一直保存,因此用作持久數(shù)據(jù);cookie只在設(shè)置的cookie過期時(shí)間之前一直有效,即使窗口或?yàn)g覽器關(guān)閉。(key:本身就是一個(gè)回話過程,關(guān)閉瀏覽器后消失,session為一個(gè)回話,當(dāng)頁(yè)面不同即使是同一頁(yè)面打開兩次,也被視為同一次回話)
          • localStorage:localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。(key:同源窗口都會(huì)共享,并且不會(huì)失效,不管窗口或者瀏覽器關(guān)閉與否都會(huì)始終生效)

          補(bǔ)充說明一下cookie的作用:

          • 保存用戶登錄狀態(tài)。例如將用戶id存儲(chǔ)于一個(gè)cookie內(nèi),這樣當(dāng)用戶下次訪問該頁(yè)面時(shí)就不需要重新登錄了,現(xiàn)在很多論壇和社區(qū)都提供這樣的功能。cookie還可以設(shè)置過期時(shí)間,當(dāng)超過時(shí)間期限后,cookie就會(huì)自動(dòng)消失。因此,系統(tǒng)往往可以提示用戶保持登錄狀態(tài)的時(shí)間:常見選項(xiàng)有一個(gè)月、三個(gè) 月、一年等。
          • 跟蹤用戶行為。例如一個(gè)天氣預(yù)報(bào)網(wǎng)站,能夠根據(jù)用戶選擇的地區(qū)顯示當(dāng)?shù)氐奶鞖馇闆r。如果每次都需要選擇所在地是煩瑣的,當(dāng)利用了 cookie后就會(huì)顯得很人性化了,系統(tǒng)能夠記住上一次訪問的地區(qū),當(dāng)下次再打開該頁(yè)面時(shí),它就會(huì)自動(dòng)顯示上次用戶所在地區(qū)的天氣情況。因?yàn)橐磺卸际窃诤?臺(tái)完成,所以這樣的頁(yè)面就像為某個(gè)用戶所定制的一樣,使用起來非常方便
          • 定制頁(yè)面。如果網(wǎng)站提供了換膚或更換布局的功能,那么可以使用cookie來記錄用戶的選項(xiàng),例如:背景色、分辨率等。當(dāng)用戶下次訪問時(shí),仍然可以保存上一次訪問的界面風(fēng)格。

          7、Cookie如何防范XSS攻擊

          參考答案
          

          XSS(跨站腳本攻擊)是指攻擊者在返回的HTML中嵌入javascript腳本,為了減輕這些攻擊,需要在HTTP頭部配上,set-cookie:

          • httponly-這個(gè)屬性可以防止XSS,它會(huì)禁止javascript腳本來訪問cookie。
          • secure - 這個(gè)屬性告訴瀏覽器僅在請(qǐng)求為https的時(shí)候發(fā)送cookie。

          結(jié)果應(yīng)該是這樣的:Set-Cookie=.....

          8、瀏覽器和 Node 事件循環(huán)的區(qū)別?

          參考答案
          

          其中一個(gè)主要的區(qū)別在于瀏覽器的event loop 和nodejs的event loop 在處理異步事件的順序是不同的,nodejs中有micro event;其中Promise屬于micro event 該異步事件的處理順序就和瀏覽器不同.nodejs V11.0以上 這兩者之間的順序就相同了.

          function test () {
             console.log('start')
              setTimeout(() => {
                  console.log('children2')
                  Promise.resolve().then(() => {console.log('children2-1')})
              }, 0)
              setTimeout(() => {
                  console.log('children3')
                  Promise.resolve().then(() => {console.log('children3-1')})
              }, 0)
              Promise.resolve().then(() => {console.log('children1')})
              console.log('end') 
          }
          
          test()
          
          // 以上代碼在node11以下版本的執(zhí)行結(jié)果(先執(zhí)行所有的宏任務(wù),再執(zhí)行微任務(wù))
          // start
          // end
          // children1
          // children2
          // children3
          // children2-1
          // children3-1
          
          // 以上代碼在node11及瀏覽器的執(zhí)行結(jié)果(順序執(zhí)行宏任務(wù)和微任務(wù))
          // start
          // end
          // children1
          // children2
          // children2-1
          // children3
          // children3-1
          

          9、簡(jiǎn)述HTTPS中間人攻擊

          參考答案
          

          https協(xié)議由 http + ssl 協(xié)議構(gòu)成,具體的鏈接過程可參考SSL或TLS握手的概述

          中間人攻擊過程如下:

          1. 服務(wù)器向客戶端發(fā)送公鑰。
          2. 攻擊者截獲公鑰,保留在自己手上。
          3. 然后攻擊者自己生成一個(gè)【偽造的】公鑰,發(fā)給客戶端。
          4. 客戶端收到偽造的公鑰后,生成加密hash值發(fā)給服務(wù)器。
          5. 攻擊者獲得加密hash值,用自己的私鑰解密獲得真秘鑰。
          6. 同時(shí)生成假的加密hash值,發(fā)給服務(wù)器。
          7. 服務(wù)器用私鑰解密獲得假秘鑰。
          8. 服務(wù)器用加秘鑰加密傳輸信息

          防范方法:

          1. 服務(wù)端在發(fā)送瀏覽器的公鑰中加入CA證書,瀏覽器可以驗(yàn)證CA證書的有效性

          10、說幾條web前端優(yōu)化策略

          參考答案
          

          (1). 減少HTTP請(qǐng)求數(shù)

          這條策略基本上所有前端人都知道,而且也是最重要最有效的。都說要減少HTTP請(qǐng)求,那請(qǐng)求多了到底會(huì)怎么樣呢?首先,每個(gè)請(qǐng)求都是有成本的,既包 含時(shí)間成本也包含資源成本。一個(gè)完整的請(qǐng)求都需要經(jīng)過DNS尋址、與服務(wù)器建立連接、發(fā)送數(shù)據(jù)、等待服務(wù)器響應(yīng)、接收數(shù)據(jù)這樣一個(gè)“漫長(zhǎng)”而復(fù)雜的過程。時(shí)間成本就是用戶需要看到或者“感受”到這個(gè)資源是必須要等待這個(gè)過程結(jié)束的,資源上由于每個(gè)請(qǐng)求都需要攜帶數(shù)據(jù),因此每個(gè)請(qǐng)求都需要占用帶寬。

          另外,由于瀏覽器進(jìn)行并發(fā)請(qǐng)求的請(qǐng)求數(shù)是有上限的,因此請(qǐng)求數(shù)多了以后,瀏覽器需要分批進(jìn)行請(qǐng)求,因此會(huì)增加用戶的等待時(shí)間,會(huì)給 用戶造成站點(diǎn)速度慢這樣一個(gè)印象,即使可能用戶能看到的第一屏的資源都已經(jīng)請(qǐng)求完了,但是瀏覽器的進(jìn)度條會(huì)一直存在。減少HTTP請(qǐng)求數(shù)的主要途徑包括:

          (2). 從設(shè)計(jì)實(shí)現(xiàn)層面簡(jiǎn)化頁(yè)面

          如果你的頁(yè)面像百度首頁(yè)一樣簡(jiǎn)單,那么接下來的規(guī)則基本上都用不著了。保持頁(yè)面簡(jiǎn)潔、減少資源的使用時(shí)最直接的。如果不是這樣,你的頁(yè)面需要華麗的皮膚,則繼續(xù)閱讀下面的內(nèi)容。

          (3). 合理設(shè)置HTTP緩存

          緩存的力量是強(qiáng)大的,恰當(dāng)?shù)木彺嬖O(shè)置可以大大的減少HTTP請(qǐng)求。以有啊首頁(yè)為例,當(dāng)瀏覽器沒有緩存的時(shí)候訪問一共會(huì)發(fā)出78個(gè)請(qǐng)求,共600多K 數(shù)據(jù)(如圖1.1),而當(dāng)?shù)诙卧L問即瀏覽器已緩存之后訪問則僅有10個(gè)請(qǐng)求,共20多K數(shù)據(jù)(如圖1.2)。(這里需要說明的是,如果直接F5刷新頁(yè)面 的話效果是不一樣的,這種情況下請(qǐng)求數(shù)還是一樣,不過被緩存資源的請(qǐng)求服務(wù)器是304響應(yīng),只有Header沒有Body,可以節(jié)省帶寬)

          怎樣才算合理設(shè)置?原則很簡(jiǎn)單,能緩存越多越好,能緩存越久越好。例如,很少變化的圖片資源可以直接通過HTTP Header中的Expires設(shè)置一個(gè)很長(zhǎng)的過期頭;變化不頻繁而又可能會(huì)變的資源可以使用Last-Modifed來做請(qǐng)求驗(yàn)證。盡可能的讓資源能夠 在緩存中待得更久。

          (4). 資源合并與壓縮

          如果可以的話,盡可能的將外部的腳本、樣式進(jìn)行合并,多個(gè)合為一個(gè)。另外,CSS、Javascript、Image都可以用相應(yīng)的工具進(jìn)行壓縮,壓縮后往往能省下不少空間。

          (5). CSS Sprites

          合并CSS圖片,減少請(qǐng)求數(shù)的又一個(gè)好辦法。

          (6). Inline Images

          使用data: URL scheme的方式將圖片嵌入到頁(yè)面或CSS中,如果不考慮資源管理上的問題的話,不失為一個(gè)好辦法。如果是嵌入頁(yè)面的話換來的是增大了頁(yè)面的體積,而且無法利用瀏覽器緩存。使用在CSS中的圖片則更為理想一些。

          (7). Lazy Load Images

          這條策略實(shí)際上并不一定能減少HTTP請(qǐng)求數(shù),但是卻能在某些條件下或者頁(yè)面剛加載時(shí)減少HTTP請(qǐng)求數(shù)。對(duì)于圖片而言,在頁(yè)面剛加載的時(shí)候可以只 加載第一屏,當(dāng)用戶繼續(xù)往后滾屏的時(shí)候才加載后續(xù)的圖片。這樣一來,假如用戶只對(duì)第一屏的內(nèi)容感興趣時(shí),那剩余的圖片請(qǐng)求就都節(jié)省了。有啊首頁(yè)曾經(jīng)的做法 是在加載的時(shí)候把第一屏之后的圖片地址緩存在Textarea標(biāo)簽中,待用戶往下滾屏的時(shí)候才“惰性”加載。

          11、你了解的瀏覽器的重繪和回流導(dǎo)致的性能問題

          參考答案
          

          重繪(Repaint)和回流(Reflow)

          重繪和回流是渲染步驟中的一小節(jié),但是這兩個(gè)步驟對(duì)于性能影響很大。

          • 重繪是當(dāng)節(jié)點(diǎn)需要更改外觀而不會(huì)影響布局的,比如改變 color就叫稱為重繪
          • 回流是布局或者幾何屬性需要改變就稱為回流。

          回流必定會(huì)發(fā)生重繪,重繪不一定會(huì)引發(fā)回流。回流所需的成本比重繪高的多,改變深層次的節(jié)點(diǎn)很可能導(dǎo)致父節(jié)點(diǎn)的一系列回流。

          所以以下幾個(gè)動(dòng)作可能會(huì)導(dǎo)致性能問題:

          • 改變 window 大小
          • 改變字體
          • 添加或刪除樣式
          • 文字改變
          • 定位或者浮動(dòng)
          • 盒模型

          很多人不知道的是,重繪和回流其實(shí)和 Event loop 有關(guān)。

          1. 當(dāng) Event loop 執(zhí)行完 Microtasks 后,會(huì)判斷 document 是否需要更新。因?yàn)闉g覽器是 60Hz 的刷新率,每 16ms 才會(huì)更新一次。
          2. 然后判斷是否有 resize或者 scroll,有的話會(huì)去觸發(fā)事件,所以 resizescroll事件也是至少 16ms 才會(huì)觸發(fā)一次,并且自帶節(jié)流功能。
          3. 判斷是否觸發(fā)了 media query
          4. 更新動(dòng)畫并且發(fā)送事件
          5. 判斷是否有全屏操作事件
          6. 執(zhí)行 requestAnimationFrame回調(diào)
          7. 執(zhí)行 IntersectionObserver回調(diào),該方法用于判斷元素是否可見,可以用于懶加載上,但是兼容性不好
          8. 更新界面
          9. 以上就是一幀中可能會(huì)做的事情。如果在一幀中有空閑時(shí)間,就會(huì)去執(zhí)行 requestIdleCallback回調(diào)。

          減少重繪和回流

          • 使用 translate 替代 top
            <div class="test"></div>
            <style>
            .test {
            position: absolute;
            top: 10px;
            width: 100px;
            height: 100px;
            background: red;
            }
            </style>
            <script>
            setTimeout(() => {
            // 引起回流
            document.querySelector('.test').style.top = '100px'
            }, 1000)
            </script>
          • 使用 visibility替換 display: none,因?yàn)榍罢咧粫?huì)引起重繪,后者會(huì)引發(fā)回流(改變了布局)
            把 DOM 離線后修改,比如:先把 DOM 給
            display:none(有一次 Reflow),然后你修改100次,然后再把它顯示出來
            不要把 DOM 結(jié)點(diǎn)的屬性值放在一個(gè)循環(huán)里當(dāng)成循環(huán)里的變量
            for(let i = 0; i < 1000; i++) {
            // 獲取 offsetTop 會(huì)導(dǎo)致回流,因?yàn)樾枰カ@取正確的值
            console.log(document.querySelector('.test').style.offsetTop)
            }
          • 不要使用 table 布局,可能很小的一個(gè)小改動(dòng)會(huì)造成整個(gè) table 的重新布局
          • 動(dòng)畫實(shí)現(xiàn)的速度的選擇,動(dòng)畫速度越快,回流次數(shù)越多,也可以選擇使用 requestAnimationFrame
          • CSS 選擇符從右往左匹配查找,避免 DOM 深度過深
          • 將頻繁運(yùn)行的動(dòng)畫變?yōu)閳D層,圖層能夠阻止該節(jié)點(diǎn)回流影響別的元素。比如對(duì)于 video標(biāo)簽,瀏覽器會(huì)自動(dòng)將該節(jié)點(diǎn)變?yōu)閳D層。

          react、Vue

          1、寫 React / Vue 項(xiàng)目時(shí)為什么要在列表組件中寫 key,其作用是什么?

          參考答案
          

          vue和react都是采用diff算法來對(duì)比新舊虛擬節(jié)點(diǎn),從而更新節(jié)點(diǎn)。在vue的diff函數(shù)中(建議先了解一下diff算法過程)。在交叉對(duì)比中,當(dāng)新節(jié)點(diǎn)跟舊節(jié)點(diǎn)頭尾交叉對(duì)比沒有結(jié)果時(shí),會(huì)根據(jù)新節(jié)點(diǎn)的key去對(duì)比舊節(jié)點(diǎn)數(shù)組中的key,從而找到相應(yīng)舊節(jié)點(diǎn)(這里對(duì)應(yīng)的是一個(gè)key => index 的map映射)。如果沒找到就認(rèn)為是一個(gè)新增節(jié)點(diǎn)。而如果沒有key,那么就會(huì)采用遍歷查找的方式去找到對(duì)應(yīng)的舊節(jié)點(diǎn)。一種一個(gè)map映射,另一種是遍歷查找。相比而言。map映射的速度更快。vue部分源碼如下:

          // vue項(xiàng)目  src/core/vdom/patch.js  -488行
          // 以下是為了閱讀性進(jìn)行格式化后的代碼
          
          // oldCh 是一個(gè)舊虛擬節(jié)點(diǎn)數(shù)組
          if (isUndef(oldKeyToIdx)) {
            oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
          }
          if(isDef(newStartVnode.key)) {
            // map 方式獲取
            idxInOld = oldKeyToIdx[newStartVnode.key]
          } else {
            // 遍歷方式獲取
            idxInOld = findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
          }
          

          創(chuàng)建map函數(shù)

          function createKeyToOldIdx (children, beginIdx, endIdx) {
            let i, key
            const map = {}
            for (i = beginIdx; i <= endIdx; ++i) {
              key = children[i].key
              if (isDef(key)) map[key] = i
            }
            return map
          }
          

          遍歷尋找

          // sameVnode 是對(duì)比新舊節(jié)點(diǎn)是否相同的函數(shù)
           function findIdxInOld (node, oldCh, start, end) {
              for (let i = start; i < end; i++) {
                const c = oldCh[i]
                
                if (isDef(c) && sameVnode(node, c)) return i
              }
            }
          

          2、React 中 setState 什么時(shí)候是同步的,什么時(shí)候是異步的?

          參考答案
          

          在React中,如果是由React引發(fā)的事件處理(比如通過onClick引發(fā)的事件處理),調(diào)用setState不會(huì)同步更新this.state,除此之外的setState調(diào)用會(huì)同步執(zhí)行this.state。所謂“除此之外”,指的是繞過React通過addEventListener直接添加的事件處理函數(shù),還有通過setTimeout/setInterval產(chǎn)生的異步調(diào)用。

          **原因:**在React的setState函數(shù)實(shí)現(xiàn)中,會(huì)根據(jù)一個(gè)變量isBatchingUpdates判斷是直接更新this.state還是放到隊(duì)列中回頭再說,而isBatchingUpdates默認(rèn)是false,也就表示setState會(huì)同步更新this.state,但是,有一個(gè)函數(shù)batchedUpdates,這個(gè)函數(shù)會(huì)把isBatchingUpdates修改為true,而當(dāng)React在調(diào)用事件處理函數(shù)之前就會(huì)調(diào)用這個(gè)batchedUpdates,造成的后果,就是由React控制的事件處理過程setState不會(huì)同步更新this.state

          3、下面輸出什么

          class Example extends React.Component {
            constructor() {
              super();
              this.state = {
                val: 0
              };
            }
            
            componentDidMount() {
              this.setState({val: this.state.val + 1});
              console.log(this.state.val);    // 第 1 次 log
          
              this.setState({val: this.state.val + 1});
              console.log(this.state.val);    // 第 2 次 log
          
              setTimeout(() => {
                this.setState({val: this.state.val + 1});
                console.log(this.state.val);  // 第 3 次 log
          
                this.setState({val: this.state.val + 1});
                console.log(this.state.val);  // 第 4 次 log
              }, 0);
            }
          
            render() {
              return null;
            }
          };
          1、第一次和第二次都是在 react 自身生命周期內(nèi),觸發(fā)時(shí) isBatchingUpdates 為 true,所以并不會(huì)直接執(zhí)行更新 state,而是加入了 dirtyComponents,所以打印時(shí)獲取的都是更新前的狀態(tài) 0。
          
          2、兩次 setState 時(shí),獲取到 this.state.val 都是 0,所以執(zhí)行時(shí)都是將 0 設(shè)置成 1,在 react 內(nèi)部會(huì)被合并掉,只執(zhí)行一次。設(shè)置完成后 state.val 值為 1。
          
          3、setTimeout 中的代碼,觸發(fā)時(shí) isBatchingUpdates 為 false,所以能夠直接進(jìn)行更新,所以連著輸出 2,3。
          
          輸出: 0 0 2 3
          

          4、為什么虛擬dom會(huì)提高性能?

          參考答案
          

          虛擬dom相當(dāng)于在js和真實(shí)dom中間加了一個(gè)緩存,利用dom diff算法避免了沒有必要的dom操作,從而提高性能。

          具體實(shí)現(xiàn)步驟如下:

          用 JavaScript 對(duì)象結(jié)構(gòu)表示 DOM 樹的結(jié)構(gòu);然后用這個(gè)樹構(gòu)建一個(gè)真正的 DOM 樹,插到文檔當(dāng)中

          當(dāng)狀態(tài)變更的時(shí)候,重新構(gòu)造一棵新的對(duì)象樹。然后用新的樹和舊的樹進(jìn)行比較,記錄兩棵樹差異

          把2所記錄的差異應(yīng)用到步驟1所構(gòu)建的真正的DOM樹上,視圖就更新了。

          css

          1、分析比較 opacity: 0、visibility: hidden、display: none 優(yōu)劣和適用場(chǎng)景

          參考答案
          

          結(jié)構(gòu):display:none: 會(huì)讓元素完全從渲染樹中消失,渲染的時(shí)候不占據(jù)任何空間, 不能點(diǎn)擊, visibility: hidden:不會(huì)讓元素從渲染樹消失,渲染元素繼續(xù)占據(jù)空間,只是內(nèi)容不可見,不能點(diǎn)擊 opacity: 0: 不會(huì)讓元素從渲染樹消失,渲染元素繼續(xù)占據(jù)空間,只是內(nèi)容不可見,可以點(diǎn)擊

          繼承:display: none:是非繼承屬性,子孫節(jié)點(diǎn)消失由于元素從渲染樹消失造成,通過修改子孫節(jié)點(diǎn)屬性無法顯示。visibility: hidden:是繼承屬性,子孫節(jié)點(diǎn)消失由于繼承了hidden,通過設(shè)置visibility: visible;可以讓子孫節(jié)點(diǎn)顯式。

          性能:displaynone : 修改元素會(huì)造成文檔回流,讀屏器不會(huì)讀取display: none元素內(nèi)容,性能消耗較大 visibility:hidden: 修改元素只會(huì)造成本元素的重繪,性能消耗較少讀屏器讀取visibility: hidden元素內(nèi)容 opacity: 0 :修改元素會(huì)造成重繪,性能消耗較少

          聯(lián)系:它們都能讓元素不可見

          2、清除浮動(dòng)的方式有哪些?比較好的是哪一種?

          參考答案
          

          常用的一般為三種.clearfix, clear:both,overflow:hidden;

          比較好是 .clearfix,偽元素萬金油版本,后兩者有局限性.

          .clearfix:after {
            visibility: hidden;
            display: block;
            font-size: 0;
            content: " ";
            clear: both;
            height: 0;
          }
          
          <!--
          為毛沒有 zoom ,_height 這些,IE6,7這類需要 csshack 不再我們考慮之內(nèi)了
          .clearfix 還有另外一種寫法,
          -->
          
          .clearfix:before, .clearfix:after {
              content:"";
              display:table;
          }
          .clearfix:after{
              clear:both;
              overflow:hidden;
          }
          .clearfix{
              zoom:1;
          }
          
          <!--
          用display:table 是為了避免外邊距margin重疊導(dǎo)致的margin塌陷,
          內(nèi)部元素默認(rèn)會(huì)成為 table-cell 單元格的形式
          -->
          

          clear:both:若是用在同一個(gè)容器內(nèi)相鄰元素上,那是賊好的,有時(shí)候在容器外就有些問題了, 比如相鄰容器的包裹層元素塌陷

          overflow:hidden:這種若是用在同個(gè)容器內(nèi),可以形成 BFC避免浮動(dòng)造成的元素塌陷

          4、css sprite 是什么,有什么優(yōu)缺點(diǎn)

          參考答案
          

          概念:將多個(gè)小圖片拼接到一個(gè)圖片中。通過 background-position 和元素尺寸調(diào)節(jié)需要顯示的背景圖案。

          優(yōu)點(diǎn):

          1. 減少 HTTP 請(qǐng)求數(shù),極大地提高頁(yè)面加載速度
          2. 增加圖片信息重復(fù)度,提高壓縮比,減少圖片大小
          3. 更換風(fēng)格方便,只需在一張或幾張圖片上修改顏色或樣式即可實(shí)現(xiàn)

          缺點(diǎn):

          1. 圖片合并麻煩
          2. 維護(hù)麻煩,修改一個(gè)圖片可能需要重新布局整個(gè)圖片,樣式

          5、link與@import的區(qū)別

          參考答案
          
          1. link是 HTML 方式, @import是 CSS 方式
          2. link最大限度支持并行下載,@import過多嵌套導(dǎo)致串行下載,出現(xiàn)FOUC
          3. link可以通過rel="alternate stylesheet"指定候選樣式
          4. 瀏覽器對(duì)link支持早于@import,可以使用@import對(duì)老瀏覽器隱藏樣式
          5. @import必須在樣式規(guī)則之前,可以在 css 文件中引用其他文件
          6. 總體來說:link 優(yōu)于@import

          6、display: block;和display: inline;的區(qū)別

          參考答案
          

          block元素特點(diǎn):

          1.處于常規(guī)流中時(shí),如果width沒有設(shè)置,會(huì)自動(dòng)填充滿父容器 2.可以應(yīng)用margin/padding 3.在沒有設(shè)置高度的情況下會(huì)擴(kuò)展高度以包含常規(guī)流中的子元素 4.處于常規(guī)流中時(shí)布局時(shí)在前后元素位置之間(獨(dú)占一個(gè)水平空間) 5.忽略vertical-align

          inline元素特點(diǎn)

          1.水平方向上根據(jù)direction依次布局

          2.不會(huì)在元素前后進(jìn)行換行

          3.受white-space控制

          4.margin/padding在豎直方向上無效,水平方向上有效

          5.width/height屬性對(duì)非替換行內(nèi)元素?zé)o效,寬度由元素內(nèi)容決定

          6.非替換行內(nèi)元素的行框高由line-height確定,替換行內(nèi)元素的行框高由height,margin,padding,border決定 7.浮動(dòng)或絕對(duì)定位時(shí)會(huì)轉(zhuǎn)換為block8.vertical-align屬性生效

          7、容器包含若干浮動(dòng)元素時(shí)如何清理浮動(dòng)

          參考答案
          
          1. 容器元素閉合標(biāo)簽前添加額外元素并設(shè)置clear: both
          2. 父元素觸發(fā)塊級(jí)格式化上下文(見塊級(jí)可視化上下文部分)
          3. 設(shè)置容器元素偽元素進(jìn)行清理推薦的清理浮動(dòng)方法
          /**
          * 在標(biāo)準(zhǔn)瀏覽器下使用
          * 1 content內(nèi)容為空格用于修復(fù)opera下文檔中出現(xiàn)
          *   contenteditable屬性時(shí)在清理浮動(dòng)元素上下的空白
          * 2 使用display使用table而不是block:可以防止容器和
          *   子元素top-margin折疊,這樣能使清理效果與BFC,IE6/7
          *   zoom: 1;一致
          **/
          
          .clearfix:before,
          .clearfix:after {
              content: " "; /* 1 */
              display: table; /* 2 */
          }
          
          .clearfix:after {
              clear: both;
          }
          
          /**
          * IE 6/7下使用
          * 通過觸發(fā)hasLayout實(shí)現(xiàn)包含浮動(dòng)
          **/
          .clearfix {
              *zoom: 1;
          }
          

          8、PNG,GIF,JPG 的區(qū)別及如何選

          參考答案
          

          GIF:

          1. 8 位像素,256 色
          2. 無損壓縮
          3. 支持簡(jiǎn)單動(dòng)畫
          4. 支持 boolean 透明
          5. 適合簡(jiǎn)單動(dòng)畫

          JPEG

          1. 顏色限于 256
          2. 有損壓縮
          3. 可控制壓縮質(zhì)量
          4. 不支持透明
          5. 適合照片

          PNG

          1. 有 PNG8 和 truecolor PNG
          2. PNG8 類似 GIF 顏色上限為 256,文件小,支持 alpha 透明度,無動(dòng)畫
          3. 適合圖標(biāo)、背景、按鈕

          9、display,float,position 的關(guān)系

          參考答案
          
          1. 如果display為 none,那么 position 和 float 都不起作用,這種情況下元素不產(chǎn)生框
          2. 否則,如果 position 值為 absolute 或者 fixed,框就是絕對(duì)定位的,float 的計(jì)算值為 none,display 根據(jù)下面的表格進(jìn)行調(diào)整。
          3. 否則,如果 float 不是 none,框是浮動(dòng)的,display 根據(jù)下表進(jìn)行調(diào)整
          4. 否則,如果元素是根元素,display 根據(jù)下表進(jìn)行調(diào)整
          5. 其他情況下 display 的值為指定值 總結(jié)起來:絕對(duì)定位、浮動(dòng)、根元素都需要調(diào)整display

          10、如何水平居中一個(gè)元素

          參考答案
          
          • 如果需要居中的元素為常規(guī)流中 inline 元素,為父元素設(shè)置text-align: center;即可實(shí)現(xiàn)
          • 如果需要居中的元素為常規(guī)流中 block 元素,1)為元素設(shè)置寬度,2)設(shè)置左右 margin 為 auto。3)IE6 下需在父元素上設(shè)置text-align: center;,再給子元素恢復(fù)需要的值
          • <body>
            <div class="content">
            aaaaaa aaaaaa a a a a a a a a
            </div>
            </body>

            <style>
            body {
            background:
            #DDD;
            text-align: center; /* 3 */
            }
            .content {
            width: 500px; /* 1 */
            text-align: left; /* 3 */
            margin: 0 auto; /* 2 */

            background: purple;
            }
            </style>
          • 如果需要居中的元素為浮動(dòng)元素,1)為元素設(shè)置寬度,2)position: relative;,3)浮動(dòng)方向偏移量(left 或者 right)設(shè)置為 50%,4)浮動(dòng)方向上的 margin 設(shè)置為元素寬度一半乘以-1
            <body>
            <div class="content">
            aaaaaa aaaaaa a a a a a a a a
            </div>
            </body>

            <style>
            body {
            background:
            #DDD;
            }
            .content {
            width: 500px; /* 1 */
            float: left;

            position: relative; /* 2 */
            left: 50%; /* 3 */
            margin-left: -250px; /* 4 */

            background-color: purple;
            }
            </style>
          • 如果需要居中的元素為絕對(duì)定位元素,1)為元素設(shè)置寬度,2)偏移量設(shè)置為 50%,3)偏移方向外邊距設(shè)置為元素寬度一半乘以-1
            <body>
            <div class="content">
            aaaaaa aaaaaa a a a a a a a a
            </div>
            </body>

            <style>
            body {
            background:
            #DDD;
            position: relative;
            }
            .content {
            width: 800px;

            position: absolute;
            left: 50%;
            margin-left: -400px;

            background-color: purple;
            }
            </style>
          • 如果需要居中的元素為絕對(duì)定位元素,1)為元素設(shè)置寬度,2)設(shè)置左右偏移量都為 0,3)設(shè)置左右外邊距都為 auto
            <body>
            <div class="content">
            aaaaaa aaaaaa a a a a a a a a
            </div>
            </body>

            <style>
            body {
            background:
            #DDD;
            position: relative;
            }
            .content {
            width: 800px;

            position: absolute;
            margin: 0 auto;
            left: 0;
            right: 0;

            background-color: purple;
            }
            </style>

          JavaScript

          1、JS有幾種數(shù)據(jù)類型,其中基本數(shù)據(jù)類型有哪些?

          參考答案
          

          七種數(shù)據(jù)類型

          • Boolean
          • Null
          • Undefined
          • Number
          • String
          • Symbol (ECMAScript 6 新定義)
          • Object

          (ES6之前)其中5種為基本類型:string,number,boolean,null,undefined,

          ES6出來的Symbol也是原始數(shù)據(jù)類型 ,表示獨(dú)一無二的值

          Object為引用類型(范圍挺大),也包括數(shù)組、函數(shù),

          2、Promise 構(gòu)造函數(shù)是同步執(zhí)行還是異步執(zhí)行,那么 then 方法呢?

          參考答案
          const promise = new Promise((resolve, reject) => {
            console.log(1)
            resolve()
            console.log(2)
          })
          
          promise.then(() => {
            console.log(3)
          })
          
          console.log(4)
          

          輸出結(jié)果是:

          1
          2
          4
          3
          promise構(gòu)造函數(shù)是同步執(zhí)行的,then方法是異步執(zhí)行的
          Promise new的時(shí)候會(huì)立即執(zhí)行里面的代碼 then是微任務(wù) 會(huì)在本次任務(wù)執(zhí)行完的時(shí)候執(zhí)行 setTimeout是宏任務(wù) 會(huì)在下次任務(wù)執(zhí)行的時(shí)候執(zhí)行
          

          3、JS的四種設(shè)計(jì)模式

          參考答案
          

          工廠模式

          簡(jiǎn)單的工廠模式可以理解為解決多個(gè)相似的問題;

          function CreatePerson(name,age,sex) {
              var obj = new Object();
              obj.name = name;
              obj.age = age;
              obj.sex = sex;
              obj.sayName = function(){
                  return this.name;
              }
              return obj;
          }
          var p1 = new CreatePerson("longen",'28','男');
          var p2 = new CreatePerson("tugenhua",'27','女');
          console.log(p1.name); // longen
          console.log(p1.age);  // 28
          console.log(p1.sex);  // 男
          console.log(p1.sayName()); // longen
          
          console.log(p2.name);  // tugenhua
          console.log(p2.age);   // 27
          console.log(p2.sex);   // 女
          console.log(p2.sayName()); // tugenhua  
          

          單例模式

          只能被實(shí)例化(構(gòu)造函數(shù)給實(shí)例添加屬性與方法)一次

          // 單體模式
          var Singleton = function(name){
              this.name = name;
          };
          Singleton.prototype.getName = function(){
              return this.name;
          }
          // 獲取實(shí)例對(duì)象
          var getInstance = (function() {
              var instance = null;
              return function(name) {
                  if(!instance) {//相當(dāng)于一個(gè)一次性閥門,只能實(shí)例化一次
                      instance = new Singleton(name);
                  }
                  return instance;
              }
          })();
          // 測(cè)試單體模式的實(shí)例,所以a===b
          var a = getInstance("aa");
          var b = getInstance("bb");  
          

          沙箱模式

          將一些函數(shù)放到自執(zhí)行函數(shù)里面,但要用閉包暴露接口,用變量接收暴露的接口,再調(diào)用里面的值,否則無法使用里面的值

          let sandboxModel=(function(){
              function sayName(){};
              function sayAge(){};
              return{
                  sayName:sayName,
                  sayAge:sayAge
              }
          })()
          

          發(fā)布者訂閱模式

          就例如如我們關(guān)注了某一個(gè)公眾號(hào),然后他對(duì)應(yīng)的有新的消息就會(huì)給你推送,

          //發(fā)布者與訂閱模式
              var shoeObj = {}; // 定義發(fā)布者
              shoeObj.list = []; // 緩存列表 存放訂閱者回調(diào)函數(shù)
          
              // 增加訂閱者
              shoeObj.listen = function(fn) {
                  shoeObj.list.push(fn); // 訂閱消息添加到緩存列表
              }
          
              // 發(fā)布消息
              shoeObj.trigger = function() {
                      for (var i = 0, fn; fn = this.list[i++];) {
                          fn.apply(this, arguments);//第一個(gè)參數(shù)只是改變fn的this,
                      }
                  }
               // 小紅訂閱如下消息
              shoeObj.listen(function(color, size) {
                  console.log("顏色是:" + color);
                  console.log("尺碼是:" + size);
              });
          
              // 小花訂閱如下消息
              shoeObj.listen(function(color, size) {
                  console.log("再次打印顏色是:" + color);
                  console.log("再次打印尺碼是:" + size);
              });
              shoeObj.trigger("紅色", 40);
              shoeObj.trigger("黑色", 42);  
          

          代碼實(shí)現(xiàn)邏輯是用數(shù)組存貯訂閱者, 發(fā)布者回調(diào)函數(shù)里面通知的方式是遍歷訂閱者數(shù)組,并將發(fā)布者內(nèi)容傳入訂閱者數(shù)組

          4、列舉出集中創(chuàng)建實(shí)例的方法

          參考答案
          

          1.字面量

          let obj={'name':'張三'}
          

          2.Object構(gòu)造函數(shù)創(chuàng)建

          let Obj=new Object()
          Obj.name='張三'
          

          3.使用工廠模式創(chuàng)建對(duì)象

          function createPerson(name){
           var o = new Object();
           o.name = name;
           };
           return o; 
          }
          var person1 = createPerson('張三');
          

          4.使用構(gòu)造函數(shù)創(chuàng)建對(duì)象

          function Person(name){
           this.name = name;
          }
          var person1 = new Person('張三');
          

          5、簡(jiǎn)述一下前端事件流

          參考答案
          

          HTML中與javascript交互是通過事件驅(qū)動(dòng)來實(shí)現(xiàn)的,例如鼠標(biāo)點(diǎn)擊事件onclick、頁(yè)面的滾動(dòng)事件onscroll等等,可以向文檔或者文檔中的元素添加事件偵聽器來預(yù)訂事件。想要知道這些事件是在什么時(shí)候進(jìn)行調(diào)用的,就需要了解一下“事件流”的概念。

          什么是事件流:事件流描述的是從頁(yè)面中接收事件的順序,DOM2級(jí)事件流包括下面幾個(gè)階段。

          • 事件捕獲階段
          • 處于目標(biāo)階段
          • 事件冒泡階段

          addEventListeneraddEventListener是DOM2 級(jí)事件新增的指定事件處理程序的操作,這個(gè)方法接收3個(gè)參數(shù):要處理的事件名、作為事件處理程序的函數(shù)和一個(gè)布爾值。最后這個(gè)布爾值參數(shù)如果是true,表示在捕獲階段調(diào)用事件處理程序;如果是false,表示在冒泡階段調(diào)用事件處理程序。

          IE只支持事件冒泡

          6、Function._proto_(getPrototypeOf)是什么?

          參考答案
          

          獲取一個(gè)對(duì)象的原型,在chrome中可以通過__proto__的形式,或者在ES6中可以通過Object.getPrototypeOf的形式。

          那么Function.proto是什么么?也就是說Function由什么對(duì)象繼承而來,我們來做如下判別。

          Function.__proto__==Object.prototype //false
          Function.__proto__==Function.prototype//true
          

          我們發(fā)現(xiàn)Function的原型也是Function。

          我們用圖可以來明確這個(gè)關(guān)系:



          7、簡(jiǎn)述一下原型 / 構(gòu)造函數(shù) / 實(shí)例

          參考答案
          
          • 原型(prototype): 一個(gè)簡(jiǎn)單的對(duì)象,用于實(shí)現(xiàn)對(duì)象的 屬性繼承。可以簡(jiǎn)單的理解成對(duì)象的爹。在 Firefox 和 Chrome 中,每個(gè)JavaScript對(duì)象中都包含一個(gè)__proto__(非標(biāo)準(zhǔn))的屬性指向它爹(該對(duì)象的原型),可obj.__proto__進(jìn)行訪問。
          • 構(gòu)造函數(shù): 可以通過new新建一個(gè)對(duì)象的函數(shù)。
          • 實(shí)例: 通過構(gòu)造函數(shù)和new創(chuàng)建出來的對(duì)象,便是實(shí)例。實(shí)例通過__proto__指向原型,通過constructor指向構(gòu)造函數(shù)

          這里來舉個(gè)栗子,以Object為例,我們常用的Object便是一個(gè)構(gòu)造函數(shù),因此我們可以通過它構(gòu)建實(shí)例。

          // 實(shí)例
          const instance = new Object()
          

          則此時(shí), 實(shí)例為instance, 構(gòu)造函數(shù)為Object,我們知道,構(gòu)造函數(shù)擁有一個(gè)prototype的屬性指向原型,因此原型為:

          // 原型
          const prototype = Object.prototype
          

          這里我們可以來看出三者的關(guān)系:

          實(shí)例.__proto__ === 原型
          
          原型.constructor === 構(gòu)造函數(shù)
          
          構(gòu)造函數(shù).prototype === 原型
          
          // 這條線其實(shí)是是基于原型進(jìn)行獲取的,可以理解成一條基于原型的映射線
          // 例如: 
          // const o = new Object()
          // o.constructor === Object   --> true
          // o.__proto__ = null;
          // o.constructor === Object   --> false
          實(shí)例.constructor === 構(gòu)造函數(shù)
          

          8、簡(jiǎn)述一下JS繼承,并舉例

          參考答案
          

          在 JS 中,繼承通常指的便是 原型鏈繼承,也就是通過指定原型,并可以通過原型鏈繼承原型上的屬性或者方法。

          • 最優(yōu)化: 圣杯模式
            var inherit = (function(c,p){
            var F = function(){};
            return function(c,p){
            F.prototype = p.prototype;
            c.prototype = new F();
            c.uber = p.prototype;
            c.prototype.constructor = c;
            }
            })();
          • 使用 ES6 的語(yǔ)法糖 class / extends

          9、函數(shù)柯里化

          參考答案
          

          在函數(shù)式編程中,函數(shù)是一等公民。那么函數(shù)柯里化是怎樣的呢?

          函數(shù)柯里化指的是將能夠接收多個(gè)參數(shù)的函數(shù)轉(zhuǎn)化為接收單一參數(shù)的函數(shù),并且返回接收余下參數(shù)且返回結(jié)果的新函數(shù)的技術(shù)。

          函數(shù)柯里化的主要作用和特點(diǎn)就是參數(shù)復(fù)用、提前返回和延遲執(zhí)行。

          在一個(gè)函數(shù)中,首先填充幾個(gè)參數(shù),然后再返回一個(gè)新的函數(shù)的技術(shù),稱為函數(shù)的柯里化。通常可用于在不侵入函數(shù)的前提下,為函數(shù) 預(yù)置通用參數(shù),供多次重復(fù)調(diào)用。

          const add = function add(x) {
              return function (y) {
                  return x + y
              }
          }
          
          const add1 = add(1)
          
          add1(2) === 3
          add1(20) === 21
          

          10、說說bind、call、apply 區(qū)別?

          參考答案
          

          callapply 都是為了解決改變 this 的指向。作用都是相同的,只是傳參的方式不同。

          除了第一個(gè)參數(shù)外,call 可以接收一個(gè)參數(shù)列表,apply 只接受一個(gè)參數(shù)數(shù)組。

          let a = {
              value: 1
          }
          function getValue(name, age) {
              console.log(name)
              console.log(age)
              console.log(this.value)
          }
          getValue.call(a, 'yck', '24')
          getValue.apply(a, ['yck', '24'])
          

          bind和其他兩個(gè)方法作用也是一致的,只是該方法會(huì)返回一個(gè)函數(shù)。并且我們可以通過 bind實(shí)現(xiàn)柯里化。

          (下面是對(duì)這三個(gè)方法的擴(kuò)展介紹)
          

          如何實(shí)現(xiàn)一個(gè) bind 函數(shù)

          對(duì)于實(shí)現(xiàn)以下幾個(gè)函數(shù),可以從幾個(gè)方面思考

          • 不傳入第一個(gè)參數(shù),那么默認(rèn)為 window
          • 改變了 this 指向,讓新的對(duì)象可以執(zhí)行該函數(shù)。那么思路是否可以變成給新的對(duì)象添加一個(gè)函數(shù),然后在執(zhí)行完以后刪除?
          Function.prototype.myBind = function (context) {
            if (typeof this !== 'function') {
              throw new TypeError('Error')
            }
            var _this = this
            var args = [...arguments].slice(1)
            // 返回一個(gè)函數(shù)
            return function F() {
              // 因?yàn)榉祷亓艘粋€(gè)函數(shù),我們可以 new F(),所以需要判斷
              if (this instanceof F) {
                return new _this(...args, ...arguments)
              }
              return _this.apply(context, args.concat(...arguments))
            }
          }
          

          如何實(shí)現(xiàn)一個(gè)call函數(shù)

          Function.prototype.myCall = function (context) {
            var context = context || window
            // 給 context 添加一個(gè)屬性
            // getValue.call(a, 'yck', '24') => a.fn = getValue
            context.fn = this
            // 將 context 后面的參數(shù)取出來
            var args = [...arguments].slice(1)
            // getValue.call(a, 'yck', '24') => a.fn('yck', '24')
            var result = context.fn(...args)
            // 刪除 fn
            delete context.fn
            return result
          }
          

          如何實(shí)現(xiàn)一個(gè)apply函數(shù)

          Function.prototype.myApply = function (context) {
            var context = context || window
            context.fn = this
          
            var result
            // 需要判斷是否存儲(chǔ)第二個(gè)參數(shù)
            // 如果存在,就將第二個(gè)參數(shù)展開
            if (arguments[1]) {
              result = context.fn(...arguments[1])
            } else {
              result = context.fn()
            }
          
            delete context.fn
            return result
          }
          

          11、箭頭函數(shù)的特點(diǎn)

          參考答案
          function a() {
              return () => {
                  return () => {
                      console.log(this)
                  }
              }
          }
          console.log(a()()())
          

          箭頭函數(shù)其實(shí)是沒有 this的,這個(gè)函數(shù)中的 this只取決于他外面的第一個(gè)不是箭頭函數(shù)的函數(shù)的 this。在這個(gè)例子中,因?yàn)檎{(diào)用 a符合前面代碼中的第一個(gè)情況,所以 thiswindow。并且 this一旦綁定了上下文,就不會(huì)被任何代碼改變。

          程序閱讀題

          1、下面程序輸出的結(jié)果是什么?

          function sayHi() {
            console.log(name);
            console.log(age);
            var name = "Lydia";
            let age = 21;
          }
          
          sayHi();
          
          • A: Lydiaundefined
          • B: LydiaReferenceError
          • C: ReferenceError21
          • D: undefinedReferenceError
          參考答案
          

          在函數(shù)中,我們首先使用var關(guān)鍵字聲明了name變量。這意味著變量在創(chuàng)建階段會(huì)被提升(JavaScript會(huì)在創(chuàng)建變量創(chuàng)建階段為其分配內(nèi)存空間),默認(rèn)值為undefined,直到我們實(shí)際執(zhí)行到使用該變量的行。我們還沒有為name變量賦值,所以它仍然保持undefined的值。

          使用let關(guān)鍵字(和const)聲明的變量也會(huì)存在變量提升,但與var不同,初始化沒有被提升。在我們聲明(初始化)它們之前,它們是不可訪問的。這被稱為“暫時(shí)死區(qū)”。當(dāng)我們?cè)诼暶髯兞恐皣L試訪問變量時(shí),JavaScript會(huì)拋出一個(gè)ReferenceError

          關(guān)于let的是否存在變量提升,我們何以用下面的例子來驗(yàn)證:

          let name = 'ConardLi'
          {
            console.log(name) // Uncaught ReferenceError: name is not defined
            let name = 'code秘密花園'
          }
          

          let變量如果不存在變量提升,console.log(name)就會(huì)輸出ConardLi,結(jié)果卻拋出了ReferenceError,那么這很好的說明了,let也存在變量提升,但是它存在一個(gè)“暫時(shí)死區(qū)”,在變量未初始化或賦值前不允許訪問。

          變量的賦值可以分為三個(gè)階段:

          • 創(chuàng)建變量,在內(nèi)存中開辟空間
          • 初始化變量,將變量初始化為undefined
          • 真正賦值

          關(guān)于letvarfunction

          • let的「創(chuàng)建」過程被提升了,但是初始化沒有提升。
          • var的「創(chuàng)建」和「初始化」都被提升了。
          • function的「創(chuàng)建」「初始化」和「賦值」都被提升了。

          2、下面代碼輸出什么

          var a = 10;
          (function () {
              console.log(a)
              a = 5
              console.log(window.a)
              var a = 20;
              console.log(a)
          })()
          

          依次輸出:undefined -> 10 -> 20

          在立即執(zhí)行函數(shù)中,var a = 20; 語(yǔ)句定義了一個(gè)局部變量 a,由于js的變量聲明提升機(jī)制,局部變量a的聲明會(huì)被提升至立即執(zhí)行函數(shù)的函數(shù)體最上方,且由于這樣的提升并不包括賦值,因此第一條打印語(yǔ)句會(huì)打印undefined,最后一條語(yǔ)句會(huì)打印20。
          
          由于變量聲明提升,a = 5; 這條語(yǔ)句執(zhí)行時(shí),局部的變量a已經(jīng)聲明,因此它產(chǎn)生的效果是對(duì)局部的變量a賦值,此時(shí)window.a 依舊是最開始賦值的10,
          

          3、下面的輸出結(jié)果是什么?

          class Chameleon {
            static colorChange(newColor) {
              this.newColor = newColor;
            }
          
            constructor({ newColor = "green" } = {}) {
              this.newColor = newColor;
            }
          }
          
          const freddie = new Chameleon({ newColor: "purple" });
          freddie.colorChange("orange");
          
          • A: orange
          • B: purple
          • C: green
          • D: TypeError

          答案: D

          colorChange方法是靜態(tài)的。靜態(tài)方法僅在創(chuàng)建它們的構(gòu)造函數(shù)中存在,并且不能傳遞給任何子級(jí)。由于freddie是一個(gè)子級(jí)對(duì)象,函數(shù)不會(huì)傳遞,所以在freddie實(shí)例上不存在freddie方法:拋出TypeError

          4、下面代碼中什么時(shí)候會(huì)輸出1?

          var a = ?;
          if(a == 1 && a == 2 && a == 3){
               conso.log(1);
          }
          參考答案
          

          因?yàn)?=會(huì)進(jìn)行隱式類型轉(zhuǎn)換 所以我們重寫toString方法就可以了

          var a = {
            i: 1,
            toString() {
              return a.i++;
            }
          }
          
          if( a == 1 && a == 2 && a == 3 ) {
            console.log(1);
          }
          

          5、下面的輸出結(jié)果是什么?

          var obj = {
              '2': 3,
              '3': 4,
              'length': 2,
              'splice': Array.prototype.splice,
              'push': Array.prototype.push
          }
          obj.push(1)
          obj.push(2)
          console.log(obj)
          參考答案
          

          1.使用第一次push,obj對(duì)象的push方法設(shè)置 obj[2]=1;obj.length+=12.使用第二次push,obj對(duì)象的push方法設(shè)置 obj[3]=2;obj.length+=13.使用console.log輸出的時(shí)候,因?yàn)閛bj具有 length 屬性和 splice 方法,故將其作為數(shù)組進(jìn)行打印 4.打印時(shí)因?yàn)閿?shù)組未設(shè)置下標(biāo)為 0 1 處的值,故打印為empty,主動(dòng) obj[0] 獲取為 undefined

          6、下面代碼輸出的結(jié)果是什么?

          var a = {n: 1};
          var b = a;
          a.x = a = {n: 2};
          
          console.log(a.x)     
          console.log(b.x)
          參考答案
          

          undefined {n:2}

          首先,a和b同時(shí)引用了{(lán)n:2}對(duì)象,接著執(zhí)行到a.x = a = {n:2}語(yǔ)句,盡管賦值是從右到左的沒錯(cuò),但是.的優(yōu)先級(jí)比=要高,所以這里首先執(zhí)行a.x,相當(dāng)于為a(或者b)所指向的{n:1}對(duì)象新增了一個(gè)屬性x,即此時(shí)對(duì)象將變?yōu)閧n:1;x:undefined}。之后按正常情況,從右到左進(jìn)行賦值,此時(shí)執(zhí)行a ={n:2}的時(shí)候,a的引用改變,指向了新對(duì)象{n:2},而b依然指向的是舊對(duì)象。之后執(zhí)行a.x = {n:2}的時(shí)候,并不會(huì)重新解析一遍a,而是沿用最初解析a.x時(shí)候的a,也即舊對(duì)象,故此時(shí)舊對(duì)象的x的值為{n:2},舊對(duì)象為 {n:1;x:{n:2}},它被b引用著。后面輸出a.x的時(shí)候,又要解析a了,此時(shí)的a是指向新對(duì)象的a,而這個(gè)新對(duì)象是沒有x屬性的,故訪問時(shí)輸出undefined;而訪問b.x的時(shí)候,將輸出舊對(duì)象的x的值,即{n:2}。

          7、下面代碼的輸出是什么?

          function checkAge(data) {
            if (data === { age: 18 }) {
              console.log("You are an adult!");
            } else if (data == { age: 18 }) {
              console.log("You are still an adult.");
            } else {
              console.log(`Hmm.. You don't have an age I guess`);
            }
          }
          
          checkAge({ age: 18 });
          參考答案
          

          Hmm.. You don't have an age I guess

          在比較相等性,原始類型通過它們的值進(jìn)行比較,而對(duì)象通過它們的引用進(jìn)行比較。JavaScript檢查對(duì)象是否具有對(duì)內(nèi)存中相同位置的引用。

          我們作為參數(shù)傳遞的對(duì)象和我們用于檢查相等性的對(duì)象在內(nèi)存中位于不同位置,所以它們的引用是不同的。

          這就是為什么{ age: 18 } === { age: 18 }{ age: 18 } == { age: 18 }返回 false的原因。

          8、下面代碼的輸出是什么?

          const obj = { 1: "a", 2: "b", 3: "c" };
          const set = new Set([1, 2, 3, 4, 5]);
          
          obj.hasOwnProperty("1");
          obj.hasOwnProperty(1);
          set.has("1");
          set.has(1);
          參考答案
          

          true` `true` `false` `true

          所有對(duì)象鍵(不包括Symbols)都會(huì)被存儲(chǔ)為字符串,即使你沒有給定字符串類型的鍵。這就是為什么obj.hasOwnProperty('1')也返回true

          上面的說法不適用于Set。在我們的Set中沒有“1”set.has('1')返回false。它有數(shù)字類型1set.has(1)返回true

          9、下面代碼的輸出是什么?

          // example 1
          var a={}, b='123', c=123;  
          a[b]='b';
          a[c]='c';  
          console.log(a[b]);
          
          ---------------------
          // example 2
          var a={}, b=Symbol('123'), c=Symbol('123');  
          a[b]='b';
          a[c]='c';  
          console.log(a[b]);
          
          ---------------------
          // example 3
          var a={}, b={key:'123'}, c={key:'456'};  
          a[b]='b';
          a[c]='c';  
          console.log(a[b]);
          參考答案
          

          這題考察的是對(duì)象的鍵名的轉(zhuǎn)換。

          • 對(duì)象的鍵名只能是字符串和 Symbol 類型。
          • 其他類型的鍵名會(huì)被轉(zhuǎn)換成字符串類型。
          • 對(duì)象轉(zhuǎn)字符串默認(rèn)會(huì)調(diào)用 toString 方法。
          // example 1
          var a={}, b='123', c=123;
          a[b]='b';
          // c 的鍵名會(huì)被轉(zhuǎn)換成字符串'123',這里會(huì)把 b 覆蓋掉。
          a[c]='c';  
          // 輸出 c
          console.log(a[b]);
          
          
          // example 2
          var a={}, b=Symbol('123'), c=Symbol('123');  
          // b 是 Symbol 類型,不需要轉(zhuǎn)換。
          a[b]='b';
          // c 是 Symbol 類型,不需要轉(zhuǎn)換。任何一個(gè) Symbol 類型的值都是不相等的,所以不會(huì)覆蓋掉 b。
          a[c]='c';
          // 輸出 b
          console.log(a[b]);
          
          
          // example 3
          var a={}, b={key:'123'}, c={key:'456'};  
          // b 不是字符串也不是 Symbol 類型,需要轉(zhuǎn)換成字符串。
          // 對(duì)象類型會(huì)調(diào)用 toString 方法轉(zhuǎn)換成字符串 [object Object]。
          a[b]='b';
          // c 不是字符串也不是 Symbol 類型,需要轉(zhuǎn)換成字符串。
          // 對(duì)象類型會(huì)調(diào)用 toString 方法轉(zhuǎn)換成字符串 [object Object]。這里會(huì)把 b 覆蓋掉。
          a[c]='c';  
          // 輸出 c
          console.log(a[b]);
          

          10、下面代碼的輸出是什么?

          (() => {
            let x, y;
            try {
              throw new Error();
            } catch (x) {
              (x = 1), (y = 2);
              console.log(x);
            }
            console.log(x);
            console.log(y);
          })();
          參考答案
          

          1` `undefined` `2

          catch塊接收參數(shù)x。當(dāng)我們傳遞參數(shù)時(shí),這與變量的x不同。這個(gè)變量x是屬于catch作用域的。

          之后,我們將這個(gè)塊級(jí)作用域的變量設(shè)置為1,并設(shè)置變量y的值。現(xiàn)在,我們打印塊級(jí)作用域的變量x,它等于1

          catch塊之外,x仍然是undefined,而y2。當(dāng)我們想在catch塊之外的console.log(x)時(shí),它返回undefined,而y返回2

          11、下面代碼的輸出結(jié)果是什么?

          function Foo() {
              Foo.a = function() {
                  console.log(1)
              }
              this.a = function() {
                  console.log(2)
              }
          }
          Foo.prototype.a = function() {
              console.log(3)
          }
          Foo.a = function() {
              console.log(4)
          }
          Foo.a();
          let obj = new Foo();
          obj.a();
          Foo.a();
          參考答案
          

          輸出順序是 4 2 1

          function Foo() {
              Foo.a = function() {
                  console.log(1)
              }
              this.a = function() {
                  console.log(2)
              }
          }
          // 以上只是 Foo 的構(gòu)建方法,沒有產(chǎn)生實(shí)例,此刻也沒有執(zhí)行
          
          Foo.prototype.a = function() {
              console.log(3)
          }
          // 現(xiàn)在在 Foo 上掛載了原型方法 a ,方法輸出值為 3
          
          Foo.a = function() {
              console.log(4)
          }
          // 現(xiàn)在在 Foo 上掛載了直接方法 a ,輸出值為 4
          
          Foo.a();
          // 立刻執(zhí)行了 Foo 上的 a 方法,也就是剛剛定義的,所以
          // # 輸出 4
          
          let obj = new Foo();
          /* 這里調(diào)用了 Foo 的構(gòu)建方法。Foo 的構(gòu)建方法主要做了兩件事:
          1. 將全局的 Foo 上的直接方法 a 替換為一個(gè)輸出 1 的方法。
          2. 在新對(duì)象上掛載直接方法 a ,輸出值為 2。
          */
          
          obj.a();
          // 因?yàn)橛兄苯臃椒?a ,不需要去訪問原型鏈,所以使用的是構(gòu)建方法里所定義的 this.a,
          // # 輸出 2
          
          Foo.a();
          // 構(gòu)建方法里已經(jīng)替換了全局 Foo 上的 a 方法,所以
          // # 輸出 1

          作者:靜觀流葉

          原文地址:https://mp.weixin.qq.com/s/PTSaytcf3xgOp6C9l3Pvjw

          **2024 高頻前端面試題匯總之CSS篇(二)**

          **引言:**

          在Web前端領(lǐng)域,CSS作為視覺呈現(xiàn)的靈魂,一直是各大公司面試考核的重點(diǎn)之一。為了幫助廣大前端開發(fā)者充分準(zhǔn)備即將到來的面試,本文將繼續(xù)盤點(diǎn)2024年高頻CSS面試題目,并通過詳盡的解析與實(shí)例代碼,帶您鞏固和拓展CSS知識(shí)體系,提升面試成功率。

          ## **一、CSS布局進(jìn)階**

          **題目1:Flexbox布局的基本原理與應(yīng)用場(chǎng)景**

          **解答:**

          Flexbox布局(彈性盒布局)是一種現(xiàn)代化的CSS布局方式,通過`display: flex`聲明父元素為彈性容器,然后通過一系列相關(guān)的屬性(如`flex-direction`、`justify-content`、`align-items`等)對(duì)子元素進(jìn)行靈活的定位與尺寸分配。

          ```html

          <!DOCTYPE html>

          <html lang="en">

          <head>

          <style>

          .container {

          display: flex;

          flex-direction: row; /* 主軸方向,默認(rèn)為水平 */

          justify-content: space-around; /* 主軸上的對(duì)齊方式 */

          align-items: center; /* 交叉軸上的對(duì)齊方式 */

          }

          .box {

          flex: 1; /* 子元素按比例分配空間 */

          border: 1px solid black;

          padding: 1em;

          margin: 0.5em;

          }

          </style>

          </head>

          <body>

          <div class="container">

          <div class="box">Box 1</div>

          <div class="box">Box 2</div>

          <div class="box">Box 3</div>

          </div>

          </body>

          </html>

          ```

          **題目2:Grid布局的特點(diǎn)與難點(diǎn)**

          **解答:**

          CSS Grid布局提供了一個(gè)二維網(wǎng)格系統(tǒng),用于定義行與列,并精確放置和對(duì)齊項(xiàng)目。相較于Flexbox,Grid布局更適合處理復(fù)雜的二維布局問題。

          ```html

          <!DOCTYPE html>

          <html lang="en">

          <head>

          <style>

          .grid-container {

          display: grid;

          grid-template-columns: repeat(3, 1fr); /* 創(chuàng)建3等寬的列 */

          grid-gap: 10px; /* 設(shè)置行與列之間的間距 */

          }

          .grid-item {

          border: 1px solid black;

          padding: 1em;

          }

          </style>

          </head>

          <body>

          <div class="grid-container">

          <div class="grid-item">Item 1</div>

          <div class="grid-item">Item 2</div>

          <div class="grid-item">Item 3</div>

          <!-- ... 更多網(wǎng)格項(xiàng) -->

          </div>

          </body>

          </html>

          ```

          ## **二、CSS選擇器與優(yōu)先級(jí)**

          **題目3:CSS選擇器的層級(jí)關(guān)系與權(quán)重計(jì)算**

          **解答:**

          CSS選擇器的優(yōu)先級(jí)由內(nèi)聯(lián)樣式(1000)、ID選擇器(100)、類選擇器(10)、屬性選擇器(10)、偽類(10)、元素選擇器(1)和通用選擇器(0)依次遞減。當(dāng)多個(gè)選擇器應(yīng)用于同一元素時(shí),優(yōu)先級(jí)高的規(guī)則生效。

          ```css

          /* 例子:優(yōu)先級(jí)比較 */

          #id .class[attr] p:hover {

          color: red; /* 優(yōu)先級(jí):1013 */

          }

          .class p {

          color: blue; /* 優(yōu)先級(jí):11 */

          }

          ```

          ## **三、CSS單位與響應(yīng)式設(shè)計(jì)**

          **題目4:rem、em與vw/vh單位在響應(yīng)式設(shè)計(jì)中的應(yīng)用**

          **解答:**

          - `rem`是相對(duì)于根元素(通常是`html`)的字體大小的單位,便于實(shí)現(xiàn)整體布局的響應(yīng)式調(diào)整。

          - `em`是相對(duì)于父元素字體大小的單位,常用于局部相對(duì)單位的設(shè)定。

          - `vw/vh`分別代表視窗寬度和高度的百分比,適合創(chuàng)建完全依賴視口大小的響應(yīng)式設(shè)計(jì)。

          ```css

          /* 示例 */

          html {

          font-size: 16px; /* 根元素字體大小 */

          }

          .container {

          width: 80%; /* 百分比單位 */

          }

          .title {

          font-size: 2rem; /* 相對(duì)于根元素字體大小 */

          }

          .subtitle {

          font-size: 1.2em; /* 相對(duì)于父元素字體大小 */

          }

          .hero-image {

          width: 100vw; /* 占滿整個(gè)視口寬度 */

          height: 50vh; /* 占視口高度的一半 */

          }

          ```

          ## **四、CSS性能優(yōu)化**

          **題目5:如何優(yōu)化CSS以提高渲染性能?**

          **解答:**

          - 減少CSS文件體積,通過合并、壓縮和精簡(jiǎn)CSS代碼。

          - 采用現(xiàn)代CSS特性替代舊有的布局和定位方式,如Flexbox和Grid布局。

          - 避免過于復(fù)雜的選擇器,減少CSS解析時(shí)間和渲染性能損耗。

          - 使用媒體查詢優(yōu)化不同設(shè)備的加載與渲染,實(shí)現(xiàn)按需加載CSS。

          - 利用CSS3硬件加速屬性(如`transform`和`will-change`)提高動(dòng)畫性能。

          以上只是部分CSS高頻面試題的解析與示例,希望能幫助您在面試前全方位地復(fù)習(xí)和掌握CSS的核心知識(shí)點(diǎn)。持續(xù)關(guān)注本系列教程,我們將持續(xù)提供更多有價(jià)值的前端面試攻略,助您在職業(yè)生涯中乘風(fēng)破浪,披荊斬棘!


          主站蜘蛛池模板: 精品人妻无码一区二区三区蜜桃一 | 国产一在线精品一区在线观看| 视频一区二区在线观看| 久久一区二区三区免费播放| 激情爆乳一区二区三区| AV天堂午夜精品一区二区三区| av无码人妻一区二区三区牛牛 | 国产内射999视频一区| 国产主播一区二区三区| 国产精品美女一区二区三区| 亚洲综合一区二区精品久久| 亚洲av无码不卡一区二区三区| 国产一区二区三区免费观在线| 成人国产精品一区二区网站| 一区二区三区在线观看中文字幕| 视频一区在线免费观看| 乱色熟女综合一区二区三区| 无码日韩精品一区二区人妻| 亚洲一区二区高清| 中文字幕在线观看一区二区 | 无码日韩精品一区二区免费| 蜜桃无码一区二区三区| 日韩一区二区视频| 亚洲综合av一区二区三区| 日韩最新视频一区二区三| 欧美一区内射最近更新| 秋霞日韩一区二区三区在线观看 | 亚洲性日韩精品一区二区三区| 国产一区二区三区精品久久呦 | 伊人久久精品无码麻豆一区| 亚洲国产成人精品无码一区二区| 亚洲一区二区免费视频| 在线观看一区二区三区av| 久久一区二区三区精华液使用方法| 精品国产一区二区三区香蕉| 精品一区二区三区无码视频| 久久免费视频一区| 久久久久人妻一区二区三区| 无码一区二区波多野结衣播放搜索| 国产AV天堂无码一区二区三区| 国产成人片视频一区二区|