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 在线成人精品国产区免费,国产综合久久久久影院,色姑娘综合网

          整合營銷服務(wù)商

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

          免費咨詢熱線:

          34道常見的HTML+CSS面試題(附答案)

          眾號【傳智播客博學谷】回復關(guān)鍵詞:前端 PS Java(100G) Python(80G) 大數(shù)據(jù) 區(qū)塊鏈 測試 PPT JS(40g+300教程) HTML 簡歷 領(lǐng)取相關(guān)學習資料!

          一、HTML

          1、<image>標簽上title屬性與alt屬性的區(qū)別是什么?

          alt屬性是為了給那些不能看到你文檔中圖像的瀏覽者提供文字說明的。且長度必須少于100個英文字符或者用戶必須保證替換文字盡可能的短。

          這包括那些使用本來就不支持圖像顯示或者圖像顯示被關(guān)閉的瀏覽器的用戶,視覺障礙的用戶和使用屏幕閱讀器的用戶等。

          title屬性為設(shè)置該屬性的元素提供建議性的信息。使用title屬性提供非本質(zhì)的額外信息。參考《alt和title屬性的區(qū)別及應(yīng)用》

          2、分別寫出以下幾個HTML標簽:文字加粗、下標、居中、字體

          加粗:<b>、<strong>

          下標:<sub>

          居中:<center>

          字體:<font>、<basefont>、參考《HTML標簽列表》

          3、請寫出至少5個html5新增的標簽,并說明其語義和應(yīng)用場景

          section:定義文檔中的一個章節(jié)

          nav:定義只包含導航鏈接的章節(jié)

          header:定義頁面或章節(jié)的頭部。它經(jīng)常包含 logo、頁面標題和導航性的目錄。

          footer:定義頁面或章節(jié)的尾部。它經(jīng)常包含版權(quán)信息、法律信息鏈接和反饋建議用的地址。

          aside:定義和頁面內(nèi)容關(guān)聯(lián)度較低的內(nèi)容——如果被刪除,剩下的內(nèi)容仍然很合理。

          參考《HTML5 標簽列表》

          4、請說說你對標簽語義化的理解?

          a. 去掉或者丟失樣式的時候能夠讓頁面呈現(xiàn)出清晰的結(jié)構(gòu)

          b. 有利于SEO:和搜索引擎建立良好溝通,有助于爬蟲抓取更多的有效信息:爬蟲依賴于標簽來確定上下文和各個關(guān)鍵字的權(quán)重;

          c. 方便其他設(shè)備解析(如屏幕閱讀器、盲人閱讀器、移動設(shè)備)以意義的方式來渲染網(wǎng)頁;

          d. 便于團隊開發(fā)和維護,語義化更具可讀性,遵循W3C標準的團隊都遵循這個標準,可以減少差異化。

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

          聲明位于文檔中的最前面,處于 標簽之前。告知瀏覽器以何種模式來渲染文檔。

          嚴格模式的排版和 JS 運作模式是,以該瀏覽器支持的最高標準運行。

          在混雜模式中,頁面以寬松的向后兼容的方式顯示。模擬老式瀏覽器的行為以防止站點無法工作。

          DOCTYPE不存在或格式不正確會導致文檔以混雜模式呈現(xiàn)。

          6、你知道多少種Doctype文檔類型?

          標簽可聲明三種 DTD 類型,分別表示嚴格版本、過渡版本以及基于框架的 HTML 文檔。

          HTML 4.01 規(guī)定了三種文檔類型:Strict、Transitional 以及 Frameset。

          XHTML 1.0 規(guī)定了三種 XML 文檔類型:Strict、Transitional 以及 Frameset。

          Standards (標準)模式(也就是嚴格呈現(xiàn)模式)用于呈現(xiàn)遵循最新標準的網(wǎng)頁,

          Quirks(包容)模式(也就是松散呈現(xiàn)模式或者兼容模式)用于呈現(xiàn)為傳統(tǒng)瀏覽器而設(shè)計的網(wǎng)頁。

          7、HTML與XHTML——二者有什么區(qū)別

          a. XHTML 元素必須被正確地嵌套。

          b. XHTML 元素必須被關(guān)閉。

          c. 標簽名必須用小寫字母。

          d. XHTML 文檔必須擁有根元素。

          參考《XHTML 與 HTML 之間的差異》

          8、html5有哪些新特性、移除了那些元素?

          a. HTML5 現(xiàn)在已經(jīng)不是 SGML 的子集,主要是關(guān)于圖像,位置,存儲,多任務(wù)等功能的增加。

          b. 拖拽釋放(Drag and drop) API

          c. 語義化更好的內(nèi)容標簽(header,nav,footer,aside,article,section)

          d. 音頻、視頻API(audio,video)

          e. 畫布(Canvas) API

          f. 地理(Geolocation) API

          g. 本地離線存儲 localStorage 長期存儲數(shù)據(jù),瀏覽器關(guān)閉后數(shù)據(jù)不丟失

          h. sessionStorage 的數(shù)據(jù)在頁面會話結(jié)束時會被清除

          i. 表單控件,calendar、date、time、email、url、search

          j. 新的技術(shù)webworker, websocket等

          移除的元素:

          a. 純表現(xiàn)的元素:basefont,big,center, s,strike,tt,u;

          b. 對可用性產(chǎn)生負面影響的元素:frame,frameset,noframes;

          9、iframe的優(yōu)缺點?

          優(yōu)點:

          a. 解決加載緩慢的第三方內(nèi)容如圖標和廣告等的加載問題

          b. iframe無刷新文件上傳

          c. iframe跨域通信

          缺點:

          a. iframe會阻塞主頁面的Onload事件

          b. 無法被一些搜索引擎索引到

          c. 頁面會增加服務(wù)器的http請求

          d. 會產(chǎn)生很多頁面,不容易管理。

          參考《iframe的一些記錄》

          10、Quirks模式是什么?它和Standards模式有什么區(qū)別?

          在寫程序時我們也會經(jīng)常遇到這樣的問題,如何保證原來的接口不變,又提供更強大的功能,尤其是新功能不兼容舊功能時。IE6以前的頁面大家都不會去寫DTD,所以IE6就假定 如果寫了DTD,就意味著這個頁面將采用對CSS支持更好的布局,而如果沒有,則采用兼容之前的布局方式。這就是Quirks模式(怪癖模式,詭異模式,怪異模式)。

          區(qū)別:總體會有布局、樣式解析和腳本執(zhí)行三個方面的區(qū)別。

          a. 盒模型:在W3C標準中,如果設(shè)置一個元素的寬度和高度,指的是元素內(nèi)容的寬度和高度,而在Quirks 模式下,IE的寬度和高度還包含了padding和border。

          b. 設(shè)置行內(nèi)元素的高寬:在Standards模式下,給等行內(nèi)元素設(shè)置wdith和height都不會生效,而在quirks模式下,則會生效。

          c. 設(shè)置百分比的高度:在standards模式下,一個元素的高度是由其包含的內(nèi)容來決定的,如果父元素沒有設(shè)置百分比的高度,子元素設(shè)置一個百分比的高度是無效的用

          d. 設(shè)置水平居中:使用margin:0 auto在standards模式下可以使元素水平居中,但在quirks模式下卻會失效。

          11、請闡述table的缺點

          a. 太深的嵌套,比如table>tr>td>h3,會導致搜索引擎讀取困難,而且,最直接的損失就是大大增加了冗余代碼量。

          b. 靈活性差,比如要將tr設(shè)置border等屬性,是不行的,得通過td

          c. 代碼臃腫,當在table中套用table的時候,閱讀代碼會顯得異常混亂

          d. 混亂的colspan與rowspan,用來布局時,頻繁使用他們會造成整個文檔順序混亂。

          e. 不夠語義

          參考《為什么說table表格布局不好?》

          12、簡述一下src與href的區(qū)別

          src用于替換當前元素;href用于在當前文檔和引用資源之間確立聯(lián)系。

          src是source的縮寫,指向外部資源的位置,指向的內(nèi)容將會嵌入到文檔中當前標簽所在位置

          href是Hypertext Reference的縮寫,指向網(wǎng)絡(luò)資源所在位置,建立和當前元素(錨點)或當前文檔(鏈接)之間的鏈接

          公眾號【傳智播客博學谷】回復關(guān)鍵詞:前端 PS Java Python 大數(shù)據(jù) 區(qū)塊鏈 測試 PPT JS HTML 簡歷 領(lǐng)取相關(guān)學習資料!

          小夕:https://juejin.im/post/5cab0c45f265da2513734390

          1. 基本類型有哪幾種?null 是對象嗎?基本數(shù)據(jù)類型和復雜數(shù)據(jù)類型存儲有什么區(qū)別?

          • 基本類型有6種,分別是undefined,null,bool,string,number,symbol(ES6新增)。
          • 雖然 typeof null 返回的值是 object,但是null不是對象,而是基本數(shù)據(jù)類型的一種。
          • 基本數(shù)據(jù)類型存儲在棧內(nèi)存,存儲的是值。
          • 復雜數(shù)據(jù)類型的值存儲在堆內(nèi)存,地址(指向堆中的值)存儲在棧內(nèi)存。當我們把對象賦值給另外一個變量的時候,復制的是地址,指向同一塊內(nèi)存空間,當其中一個對象改變時,另一個對象也會變化。

          2. typeof 是否正確判斷類型? instanceof呢? instanceof 的實現(xiàn)原理是什么?

          首先 typeof 能夠正確的判斷基本數(shù)據(jù)類型,但是除了 null, typeof null輸出的是對象。

          但是對象來說,typeof 不能正確的判斷其類型, typeof 一個函數(shù)可以輸出 'function',而除此之外,輸出的全是 object,這種情況下,我們無法準確的知道對象的類型。

          instanceof可以準確的判斷復雜數(shù)據(jù)類型,但是不能正確判斷基本數(shù)據(jù)類型。

          instanceof 是通過原型鏈判斷的,A instanceof B, 在A的原型鏈中層層查找,是否有原型等于B.prototype,如果一直找到A的原型鏈的頂端(null;即Object.__proto__.__proto__),仍然不等于B.prototype,那么返回false,否則返回true.

          instanceof的實現(xiàn)代碼:

          // L instanceof R
          function instance_of(L, R) {//L 表示左表達式,R 表示右表達式
           var O = R.prototype;// 取 R 的顯式原型
           L = L.__proto__; // 取 L 的隱式原型
           while (true) { 
           if (L === null) //已經(jīng)找到頂層
           return false; 
           if (O === L) //當 O 嚴格等于 L 時,返回 true
           return true; 
           L = L.__proto__; //繼續(xù)向上一層原型鏈查找
           } 
          }
          

          3. for of , for in 和 forEach,map 的區(qū)別。

          • for...of循環(huán):具有 iterator 接口,就可以用for...of循環(huán)遍歷它的成員(屬性值)。for...of循環(huán)可以使用的范圍包括數(shù)組、Set 和 Map 結(jié)構(gòu)、某些類似數(shù)組的對象、Generator 對象,以及字符串。for...of循環(huán)調(diào)用遍歷器接口,數(shù)組的遍歷器接口只返回具有數(shù)字索引的屬性。對于普通的對象,for...of結(jié)構(gòu)不能直接使用,會報錯,必須部署了 Iterator 接口后才能使用。可以中斷循環(huán)。
          • for...in循環(huán):遍歷對象自身的和繼承的可枚舉的屬性, 不能直接獲取屬性值。可以中斷循環(huán)。
          • forEach: 只能遍歷數(shù)組,不能中斷,沒有返回值(或認為返回值是undefined)。
          • map: 只能遍歷數(shù)組,不能中斷,返回值是修改后的數(shù)組。

          PS: Object.keys():返回給定對象所有可枚舉屬性的字符串數(shù)組。

          關(guān)于forEach是否會改變原數(shù)組的問題,有些小伙伴提出了異議,為此我寫了代碼測試了下(注意數(shù)組項是復雜數(shù)據(jù)類型的情況)。 除了forEach之外,map等API,也有同樣的問題。

          let arry = [1, 2, 3, 4];
          arry.forEach((item) => {
           item *= 10;
          });
          console.log(arry); //[1, 2, 3, 4]
          arry.forEach((item) => {
           arry[1] = 10; //直接操作數(shù)組
          });
          console.log(arry); //[ 1, 10, 3, 4 ]
          let arry2 = [
           { name: "Yve" },
           { age: 20 }
          ];
          arry2.forEach((item) => {
           item.name = 10;
          });
          console.log(arry2);//[ { name: 10 }, { age: 20, name: 10 } ]
          

          如還不了解 iterator 接口或 for...of, 請先閱讀ES6文檔: Iterator 和 for...of 循環(huán)

          更多細節(jié)請戳: github.com/YvetteLau/B…


          4. 如何判斷一個變量是不是數(shù)組?

          • 使用 Array.isArray 判斷,如果返回 true, 說明是數(shù)組
          • 使用 instanceof Array 判斷,如果返回true, 說明是數(shù)組
          • 使用 Object.prototype.toString.call 判斷,如果值是 [object Array], 說明是數(shù)組
          • 通過 constructor 來判斷,如果是數(shù)組,那么 arr.constructor === Array. (不準確,因為我們可以指定 obj.constructor = Array)
          function fn() {
           console.log(Array.isArray(arguments)); //false; 因為arguments是類數(shù)組,但不是數(shù)組
           console.log(Array.isArray([1,2,3,4])); //true
           console.log(arguments instanceof Array); //fasle
           console.log([1,2,3,4] instanceof Array); //true
           console.log(Object.prototype.toString.call(arguments)); //[object Arguments]
           console.log(Object.prototype.toString.call([1,2,3,4])); //[object Array]
           console.log(arguments.constructor === Array); //false
           arguments.constructor = Array;
           console.log(arguments.constructor === Array); //true
           console.log(Array.isArray(arguments)); //false
          }
          fn(1,2,3,4);
          

          5. 類數(shù)組和數(shù)組的區(qū)別是什么?

          類數(shù)組:

          1)擁有l(wèi)ength屬性,其它屬性(索引)為非負整數(shù)(對象中的索引會被當做字符串來處理);

          2)不具有數(shù)組所具有的方法;

          類數(shù)組是一個普通對象,而真實的數(shù)組是Array類型。

          常見的類數(shù)組有: 函數(shù)的參數(shù) arguments, DOM 對象列表(比如通過 document.querySelectorAll 得到的列表), jQuery 對象 (比如 $("div")).

          類數(shù)組可以轉(zhuǎn)換為數(shù)組:

          //第一種方法
          Array.prototype.slice.call(arrayLike, start);
          //第二種方法
          [...arrayLike];
          //第三種方法:
          Array.from(arrayLike);
          

          PS: 任何定義了遍歷器(Iterator)接口的對象,都可以用擴展運算符轉(zhuǎn)為真正的數(shù)組。

          Array.from方法用于將兩類對象轉(zhuǎn)為真正的數(shù)組:類似數(shù)組的對象(array-like object)和可遍歷(iterable)的對象。


          6. == 和 === 有什么區(qū)別?

          === 不需要進行類型轉(zhuǎn)換,只有類型相同并且值相等時,才返回 true.

          == 如果兩者類型不同,首先需要進行類型轉(zhuǎn)換。具體流程如下:

          1. 首先判斷兩者類型是否相同,如果相等,判斷值是否相等.
          2. 如果類型不同,進行類型轉(zhuǎn)換
          3. 判斷比較的是否是 null 或者是 undefined, 如果是, 返回 true .
          4. 判斷兩者類型是否為 string 和 number, 如果是, 將字符串轉(zhuǎn)換成 number
          5. 判斷其中一方是否為 boolean, 如果是, 將 boolean 轉(zhuǎn)為 number 再進行判斷
          6. 判斷其中一方是否為 object 且另一方為 string、number 或者 symbol , 如果是, 將 object 轉(zhuǎn)為原始類型再進行判斷
          let person1 = {
           age: 25
          }
          let person2 = person1;
          person2.gae = 20;
          console.log(person1 === person2); //true,注意復雜數(shù)據(jù)類型,比較的是引用地址
          

          思考: [] == ![]

          我們來分析一下: [] == ![] 是true還是false?

          1. 首先,我們需要知道 ! 優(yōu)先級是高于 == (更多運算符優(yōu)先級可查看: 運算符優(yōu)先級)
          2. ![] 引用類型轉(zhuǎn)換成布爾值都是true,因此![]的是false
          3. 根據(jù)上面的比較步驟中的第五條,其中一方是 boolean,將 boolean 轉(zhuǎn)為 number 再進行判斷,false轉(zhuǎn)換成 number,對應(yīng)的值是 0.
          4. 根據(jù)上面比較步驟中的第六條,有一方是 number,那么將object也轉(zhuǎn)換成Number,空數(shù)組轉(zhuǎn)換成數(shù)字,對應(yīng)的值是0.(空數(shù)組轉(zhuǎn)換成數(shù)字,對應(yīng)的值是0,如果數(shù)組中只有一個數(shù)字,那么轉(zhuǎn)成number就是這個數(shù)字,其它情況,均為NaN)
          5. 0 == 0; 為true

          7. ES6中的class和ES5的類有什么區(qū)別?

          1. ES6 class 內(nèi)部所有定義的方法都是不可枚舉的;
          2. ES6 class 必須使用 new 調(diào)用;
          3. ES6 class 不存在變量提升;
          4. ES6 class 默認即是嚴格模式;
          5. ES6 class 子類必須在父類的構(gòu)造函數(shù)中調(diào)用super(),這樣才有this對象;ES5中類繼承的關(guān)系是相反的,先有子類的this,然后用父類的方法應(yīng)用在this上。

          8. 數(shù)組的哪些API會改變原數(shù)組?

          修改 原數(shù)組的API有:

          splice/reverse/fill/copyWithin/sort/push/pop/unshift/shift

          不修改 原數(shù)組的API有:

          slice/map/forEach/every/filter/reduce/entries/find

          注: 數(shù)組的每一項是簡單數(shù)據(jù)類型,且未直接操作數(shù)組的情況下(稍后會對此題重新作答)。


          9. let、const 以及 var 的區(qū)別是什么?

          • let 和 const 定義的變量不會出現(xiàn)變量提升,而 var 定義的變量會提升。
          • let 和 const 是JS中的塊級作用域
          • let 和 const 不允許重復聲明(會拋出錯誤)
          • let 和 const 定義的變量在定義語句之前,如果使用會拋出錯誤(形成了暫時性死區(qū)),而 var 不會。
          • const 聲明一個只讀的常量。一旦聲明,常量的值就不能改變(如果聲明是一個對象,那么不能改變的是對象的引用地址)

          10. 在JS中什么是變量提升?什么是暫時性死區(qū)?

          變量提升就是變量在聲明之前就可以使用,值為undefined。

          在代碼塊內(nèi),使用 let/const 命令聲明變量之前,該變量都是不可用的(會拋出錯誤)。這在語法上,稱為“暫時性死區(qū)”。暫時性死區(qū)也意味著 typeof 不再是一個百分百安全的操作。

          typeof x; // ReferenceError(暫時性死區(qū),拋錯)
          let x;
          復制代碼
          typeof y; // 值是undefined,不會報錯
          

          暫時性死區(qū)的本質(zhì)就是,只要一進入當前作用域,所要使用的變量就已經(jīng)存在了,但是不可獲取,只有等到聲明變量的那一行代碼出現(xiàn),才可以獲取和使用該變量。


          11. 如何正確的判斷this? 箭頭函數(shù)的this是什么?

          this的綁定規(guī)則有四種:默認綁定,隱式綁定,顯式綁定,new綁定.

          1. 函數(shù)是否在 new 中調(diào)用(new綁定),如果是,那么 this 綁定的是新創(chuàng)建的對象【前提是構(gòu)造函數(shù)中沒有返回對象或者是function,否則this指向返回的對象/function】。
          2. 函數(shù)是否通過 call,apply 調(diào)用,或者使用了 bind (即硬綁定),如果是,那么this綁定的就是指定的對象。
          3. 函數(shù)是否在某個上下文對象中調(diào)用(隱式綁定),如果是的話,this 綁定的是那個上下文對象。一般是 obj.foo()
          4. 如果以上都不是,那么使用默認綁定。如果在嚴格模式下,則綁定到 undefined,否則綁定到全局對象。
          5. 如果把 null 或者 undefined 作為 this 的綁定對象傳入 call、apply 或者 bind, 這些值在調(diào)用時會被忽略,實際應(yīng)用的是默認綁定規(guī)則。
          6. 箭頭函數(shù)沒有自己的 this, 它的this繼承于上一層代碼塊的this。

          測試下是否已經(jīng)成功Get了此知識點(瀏覽器執(zhí)行環(huán)境):

          var number = 5;
          var obj = {
           number: 3,
           fn1: (function () {
           var number;
           this.number *= 2;
           number = number * 2;
           number = 3;
           return function () {
           var num = this.number;
           this.number *= 2;
           console.log(num);
           number *= 3;
           console.log(number);
           }
           })()
          }
          var fn1 = obj.fn1;
          fn1.call(null);
          obj.fn1();
          console.log(window.number);
          


          12. 詞法作用域和this的區(qū)別。

          • 詞法作用域是由你在寫代碼時將變量和塊作用域?qū)懺谀睦飦頉Q定的
          • this 是在調(diào)用時被綁定的,this 指向什么,完全取決于函數(shù)的調(diào)用位置.

          13. 談?wù)勀銓S執(zhí)行上下文棧和作用域鏈的理解。

          執(zhí)行上下文就是當前 JavaScript 代碼被解析和執(zhí)行時所在環(huán)境, JS執(zhí)行上下文棧可以認為是一個存儲函數(shù)調(diào)用的棧結(jié)構(gòu),遵循先進后出的原則。

          • JavaScript執(zhí)行在單線程上,所有的代碼都是排隊執(zhí)行。
          • 一開始瀏覽器執(zhí)行全局的代碼時,首先創(chuàng)建全局的執(zhí)行上下文,壓入執(zhí)行棧的頂部。
          • 每當進入一個函數(shù)的執(zhí)行就會創(chuàng)建函數(shù)的執(zhí)行上下文,并且把它壓入執(zhí)行棧的頂部。當前函數(shù)執(zhí)行-完成后,當前函數(shù)的執(zhí)行上下文出棧,并等待垃圾回收。
          • 瀏覽器的JS執(zhí)行引擎總是訪問棧頂?shù)膱?zhí)行上下文。
          • 全局上下文只有唯一的一個,它在瀏覽器關(guān)閉時出棧。

          作用域鏈: 無論是 LHS 還是 RHS 查詢,都會在當前的作用域開始查找,如果沒有找到,就會向上級作用域繼續(xù)查找目標標識符,每次上升一個作用域,一直到全局作用域為止。


          14. 什么是閉包?閉包的作用是什么?閉包有哪些使用場景?

          閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù),創(chuàng)建閉包最常用的方式就是在一個函數(shù)內(nèi)部創(chuàng)建另一個函數(shù)。

          閉包的作用有:

          1. 封裝私有變量
          2. 模仿塊級作用域(ES5中沒有塊級作用域)
          3. 實現(xiàn)JS的模塊

          15. call、apply有什么區(qū)別?call,aplly和bind的內(nèi)部是如何實現(xiàn)的?

          call 和 apply 的功能相同,區(qū)別在于傳參的方式不一樣:

          • fn.call(obj, arg1, arg2, ...),調(diào)用一個函數(shù), 具有一個指定的this值和分別地提供的參數(shù)(參數(shù)的列表)。
          • fn.apply(obj, [argsArray]),調(diào)用一個函數(shù),具有一個指定的this值,以及作為一個數(shù)組(或類數(shù)組對象)提供的參數(shù)。

          call核心:

          • 將函數(shù)設(shè)為傳入?yún)?shù)的屬性
          • 指定this到函數(shù)并傳入給定參數(shù)執(zhí)行函數(shù)
          • 如果不傳入?yún)?shù)或者參數(shù)為null,默認指向為 window / global
          • 刪除參數(shù)上的函數(shù)
          Function.prototype.call = function (context) {
           /** 如果第一個參數(shù)傳入的是 null 或者是 undefined, 那么指向this指向 window/global */
           /** 如果第一個參數(shù)傳入的不是null或者是undefined, 那么必須是一個對象 */
           if (!context) {
           //context為null或者是undefined
           context = typeof window === 'undefined' ? global : window;
           }
           context.fn = this; //this指向的是當前的函數(shù)(Function的實例)
           let rest = [...arguments].slice(1);//獲取除了this指向?qū)ο笠酝獾膮?shù), 空數(shù)組slice后返回的仍然是空數(shù)組
           let result = context.fn(...rest); //隱式綁定,當前函數(shù)的this指向了context.
           delete context.fn;
           return result;
          }
          //測試代碼
          var foo = {
           name: 'Selina'
          }
          var name = 'Chirs';
          function bar(job, age) {
           console.log(this.name);
           console.log(job, age);
          }
          bar.call(foo, 'programmer', 20);
          // Selina programmer 20
          bar.call(null, 'teacher', 25);
          // 瀏覽器環(huán)境: Chirs teacher 25; node 環(huán)境: undefined teacher 25
          

          apply:

          apply的實現(xiàn)和call很類似,但是需要注意他們的參數(shù)是不一樣的,apply的第二個參數(shù)是數(shù)組或類數(shù)組.

          Function.prototype.apply = function (context, rest) {
           if (!context) {
           //context為null或者是undefined時,設(shè)置默認值
           context = typeof window === 'undefined' ? global : window;
           }
           context.fn = this;
           let result;
           if(rest === undefined || rest === null) {
           //undefined 或者 是 null 不是 Iterator 對象,不能被 ...
           result = context.fn(rest);
           }else if(typeof rest === 'object') {
           result = context.fn(...rest);
           }
           delete context.fn;
           return result;
          }
          var foo = {
           name: 'Selina'
          }
          var name = 'Chirs';
          function bar(job, age) {
           console.log(this.name);
           console.log(job, age);
          }
          bar.apply(foo, ['programmer', 20]);
          // Selina programmer 20
          bar.apply(null, ['teacher', 25]);
          // 瀏覽器環(huán)境: Chirs programmer 20; node 環(huán)境: undefined teacher 25
          

          bind

          bind 和 call/apply 有一個很重要的區(qū)別,一個函數(shù)被 call/apply 的時候,會直接調(diào)用,但是 bind 會創(chuàng)建一個新函數(shù)。當這個新函數(shù)被調(diào)用時,bind() 的第一個參數(shù)將作為它運行時的 this,之后的一序列參數(shù)將會在傳遞的實參前傳入作為它的參數(shù)。

          Function.prototype.bind = function(context) {
           if(typeof this !== "function"){
           throw new TypeError("not a function");
           }
           let self = this;
           let args = [...arguments].slice(1);
           function Fn() {};
           Fn.prototype = this.prototype;
           let bound = function() {
           let res = [...args, ...arguments]; //bind傳遞的參數(shù)和函數(shù)調(diào)用時傳遞的參數(shù)拼接
           context = this instanceof Fn ? this : context || this;
           return self.apply(context, res);
           }
           //原型鏈
           bound.prototype = new Fn();
           return bound;
          }
          var name = 'Jack';
          function person(age, job, gender){
           console.log(this.name , age, job, gender);
          }
          var Yve = {name : 'Yvette'};
          let result = person.bind(Yve, 22, 'enginner')('female');	
          


          16. new的原理是什么?通過new的方式創(chuàng)建對象和通過字面量創(chuàng)建有什么區(qū)別?

          new:

          1. 創(chuàng)建一個新對象。
          2. 這個新對象會被執(zhí)行[[原型]]連接。
          3. 屬性和方法被加入到 this 引用的對象中。并執(zhí)行了構(gòu)造函數(shù)中的方法.
          4. 如果函數(shù)沒有返回其他對象,那么this指向這個新對象,否則this指向構(gòu)造函數(shù)中返回的對象。
          function new(func) {
           let target = {};
           target.__proto__ = func.prototype;
           let res = func.call(target);
           if (res && typeof(res) == "object" || typeof(res) == "function") {
           	return res;
           }
           return target;
          }
          

          字面量創(chuàng)建對象,不會調(diào)用 Object構(gòu)造函數(shù), 簡潔且性能更好;

          new Object() 方式創(chuàng)建對象本質(zhì)上是方法調(diào)用,涉及到在proto鏈中遍歷該方法,當找到該方法后,又會生產(chǎn)方法調(diào)用必須的 堆棧信息,方法調(diào)用結(jié)束后,還要釋放該堆棧,性能不如字面量的方式。

          通過對象字面量定義對象時,不會調(diào)用Object構(gòu)造函數(shù)。


          17. 談?wù)勀銓υ偷睦斫猓?/strong>

          在 JavaScript 中,每當定義一個對象(函數(shù)也是對象)時候,對象中都會包含一些預(yù)定義的屬性。其中每個函數(shù)對象都有一個prototype 屬性,這個屬性指向函數(shù)的原型對象。使用原型對象的好處是所有對象實例共享它所包含的屬性和方法。


          18. 什么是原型鏈?【原型鏈解決的是什么問題?】

          原型鏈解決的主要是繼承問題。

          每個對象擁有一個原型對象,通過 proto (讀音: dunder proto) 指針指向其原型對象,并從中繼承方法和屬性,同時原型對象也可能擁有原型,這樣一層一層,最終指向 null(Object.proptotype.__proto__ 指向的是null)。這種關(guān)系被稱為原型鏈 (prototype chain),通過原型鏈一個對象可以擁有定義在其他對象中的屬性和方法。

          構(gòu)造函數(shù) Parent、Parent.prototype 和 實例 p 的關(guān)系如下:(p.__proto__ === Parent.prototype)

          19. prototype 和 __proto__ 區(qū)別是什么?

          prototype是構(gòu)造函數(shù)的屬性。

          __proto__ 是每個實例都有的屬性,可以訪問 [[prototype]] 屬性。

          實例的__proto__ 與其構(gòu)造函數(shù)的prototype指向的是同一個對象。

          function Student(name) {
           this.name = name;
          }
          Student.prototype.setAge = function(){
           this.age=20;
          }
          let Jack = new Student('jack');
          console.log(Jack.__proto__);
          //console.log(Object.getPrototypeOf(Jack));;
          console.log(Student.prototype);
          console.log(Jack.__proto__ === Student.prototype);//true
          

          20. 使用ES5實現(xiàn)一個繼承?

          組合繼承(最常用的繼承方式)

          function SuperType(name) {
           this.name = name;
           this.colors = ['red', 'blue', 'green'];
          }
          SuperType.prototype.sayName = function() {
           console.log(this.name);
          }
          function SubType(name, age) {
           SuperType.call(this, name);
           this.age = age;
          }
          SubType.prototype = new SuperType();
          SubType.prototype.constructor = SubType;
          SubType.prototype.sayAge = function() {
           console.log(this.age);
          }
          
          

          其它繼承方式實現(xiàn),可以參考《JavaScript高級程序設(shè)計》


          21. 什么是深拷貝?深拷貝和淺拷貝有什么區(qū)別?

          淺拷貝是指只復制第一層對象,但是當對象的屬性是引用類型時,實質(zhì)復制的是其引用,當引用指向的值改變時也會跟著變化。

          深拷貝復制變量值,對于非基本類型的變量,則遞歸至基本類型變量后,再復制。深拷貝后的對象與原來的對象是完全隔離的,互不影響,對一個對象的修改并不會影響另一個對象。

          實現(xiàn)一個深拷貝:

          function deepClone(obj) { //遞歸拷貝
           if(obj === null) return null; //null 的情況
           if(obj instanceof RegExp) return new RegExp(obj);
           if(obj instanceof Date) return new Date(obj);
           if(typeof obj !== 'object') {
           //如果不是復雜數(shù)據(jù)類型,直接返回
           return obj;
           }
           /**
           * 如果obj是數(shù)組,那么 obj.constructor 是 [Function: Array]
           * 如果obj是對象,那么 obj.constructor 是 [Function: Object]
           */
           let t = new obj.constructor();
           for(let key in obj) {
           //如果 obj[key] 是復雜數(shù)據(jù)類型,遞歸
           t[key] = deepClone(obj[key]);
           }
           return t;
          }
          


          22. 防抖和節(jié)流的區(qū)別是什么?防抖和節(jié)流的實現(xiàn)。

          防抖和節(jié)流的作用都是防止函數(shù)多次調(diào)用。區(qū)別在于,假設(shè)一個用戶一直觸發(fā)這個函數(shù),且每次觸發(fā)函數(shù)的間隔小于設(shè)置的時間,防抖的情況下只會調(diào)用一次,而節(jié)流的情況會每隔一定時間調(diào)用一次函數(shù)。

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

          function debounce(func, wait, immediate = true) {
           let timer;
           // 延遲執(zhí)行函數(shù)
           const later = (context, args) => setTimeout(() => {
           timer = null;// 倒計時結(jié)束
           if (!immediate) {
           func.apply(context, args);
           //執(zhí)行回調(diào)
           context = args = null;
           }
           }, wait);
           let debounced = function (...params) {
           let context = this;
           let args = params;
           if (!timer) {
           timer = later(context, args);
           if (immediate) {
           //立即執(zhí)行
           func.apply(context, args);
           }
           } else {
           clearTimeout(timer);
           //函數(shù)在每個等待時延的結(jié)束被調(diào)用
           timer = later(context, args);
           }
           }
           debounced.cancel = function () {
           clearTimeout(timer);
           timer = null;
           };
           return debounced;
          };
          

          防抖的應(yīng)用場景:

          • 每次 resize/scroll 觸發(fā)統(tǒng)計事件
          • 文本輸入的驗證(連續(xù)輸入文字后發(fā)送 AJAX 請求進行驗證,驗證一次就好)

          節(jié)流(throttle): 高頻事件在規(guī)定時間內(nèi)只會執(zhí)行一次,執(zhí)行一次后,只有大于設(shè)定的執(zhí)行周期后才會執(zhí)行第二次。

          //underscore.js
          function throttle(func, wait, options) {
           var timeout, context, args, result;
           var previous = 0;
           if (!options) options = {};
           var later = function () {
           previous = options.leading === false ? 0 : Date.now() || new Date().getTime();
           timeout = null;
           result = func.apply(context, args);
           if (!timeout) context = args = null;
           };
           var throttled = function () {
           var now = Date.now() || new Date().getTime();
           if (!previous && options.leading === false) previous = now;
           var remaining = wait - (now - previous);
           context = this;
           args = arguments;
           if (remaining <= 0 || remaining > wait) {
           if (timeout) {
           clearTimeout(timeout);
           timeout = null;
           }
           previous = now;
           result = func.apply(context, args);
           if (!timeout) context = args = null;
           } else if (!timeout && options.trailing !== false) {
           // 判斷是否設(shè)置了定時器和 trailing
           timeout = setTimeout(later, remaining);
           }
           return result;
           };
           throttled.cancel = function () {
           clearTimeout(timeout);
           previous = 0;
           timeout = context = args = null;
           };
           return throttled;
          };
          

          函數(shù)節(jié)流的應(yīng)用場景有:

          • DOM 元素的拖拽功能實現(xiàn)(mousemove)
          • 射擊游戲的 mousedown/keydown 事件(單位時間只能發(fā)射一顆子彈)
          • 計算鼠標移動的距離(mousemove)
          • Canvas 模擬畫板功能(mousemove)
          • 搜索聯(lián)想(keyup)
          • 監(jiān)聽滾動事件判斷是否到頁面底部自動加載更多:給 scroll 加了 debounce 后,只有用戶停止?jié)L動后,才會判斷是否到了頁面底部;如果是 throttle 的話,只要頁面滾動就會間隔一段時間判斷一次

          23. 取數(shù)組的最大值(ES5、ES6)

          // ES5 的寫法
          Math.max.apply(null, [14, 3, 77, 30]);
          // ES6 的寫法
          Math.max(...[14, 3, 77, 30]);
          // reduce
          [14,3,77,30].reduce((accumulator, currentValue)=>{
           return accumulator = accumulator > currentValue ? accumulator : currentValue
          });
          

          24. ES6新的特性有哪些?

          1. 新增了塊級作用域(let,const)
          2. 提供了定義類的語法糖(class)
          3. 新增了一種基本數(shù)據(jù)類型(Symbol)
          4. 新增了變量的解構(gòu)賦值
          5. 函數(shù)參數(shù)允許設(shè)置默認值,引入了rest參數(shù),新增了箭頭函數(shù)
          6. 數(shù)組新增了一些API,如 isArray / from / of 方法;數(shù)組實例新增了 entries(),keys() 和 values() 等方法
          7. 對象和數(shù)組新增了擴展運算符
          8. ES6 新增了模塊化(import/export)
          9. ES6 新增了 Set 和 Map 數(shù)據(jù)結(jié)構(gòu)
          10. ES6 原生提供 Proxy 構(gòu)造函數(shù),用來生成 Proxy 實例
          11. ES6 新增了生成器(Generator)和遍歷器(Iterator)

          25. setTimeout倒計時為什么會出現(xiàn)誤差?

          setTimeout() 只是將事件插入了“任務(wù)隊列”,必須等當前代碼(執(zhí)行棧)執(zhí)行完,主線程才會去執(zhí)行它指定的回調(diào)函數(shù)。要是當前代碼消耗時間很長,也有可能要等很久,所以并沒辦法保證回調(diào)函數(shù)一定會在 setTimeout() 指定的時間執(zhí)行。所以, setTimeout() 的第二個參數(shù)表示的是最少時間,并非是確切時間。

          HTML5標準規(guī)定了 setTimeout() 的第二個參數(shù)的最小值不得小于4毫秒,如果低于這個值,則默認是4毫秒。在此之前。老版本的瀏覽器都將最短時間設(shè)為10毫秒。另外,對于那些DOM的變動(尤其是涉及頁面重新渲染的部分),通常是間隔16毫秒執(zhí)行。這時使用 requestAnimationFrame() 的效果要好于 setTimeout();


          26. 為什么 0.1 + 0.2 != 0.3 ?

          0.1 + 0.2 != 0.3 是因為在進制轉(zhuǎn)換和進階運算的過程中出現(xiàn)精度損失。

          下面是詳細解釋:

          JavaScript使用 Number 類型表示數(shù)字(整數(shù)和浮點數(shù)),使用64位表示一個數(shù)字。

          圖片說明:

          • 第0位:符號位,0表示正數(shù),1表示負數(shù)(s)
          • 第1位到第11位:儲存指數(shù)部分(e)
          • 第12位到第63位:儲存小數(shù)部分(即有效數(shù)字)f

          計算機無法直接對十進制的數(shù)字進行運算, 需要先對照 IEEE 754 規(guī)范轉(zhuǎn)換成二進制,然后對階運算。

          1.進制轉(zhuǎn)換

          0.1和0.2轉(zhuǎn)換成二進制后會無限循環(huán)

          0.1 -> 0.0001100110011001...(無限循環(huán))
          0.2 -> 0.0011001100110011...(無限循環(huán))
          

          但是由于IEEE 754尾數(shù)位數(shù)限制,需要將后面多余的位截掉,這樣在進制之間的轉(zhuǎn)換中精度已經(jīng)損失。

          2.對階運算

          由于指數(shù)位數(shù)不相同,運算時需要對階運算 這部分也可能產(chǎn)生精度損失。

          按照上面兩步運算(包括兩步的精度損失),最后的結(jié)果是

          0.0100110011001100110011001100110011001100110011001100

          結(jié)果轉(zhuǎn)換成十進制之后就是 0.30000000000000004。

          27. promise 有幾種狀態(tài), Promise 有什么優(yōu)缺點 ?

          promise有三種狀態(tài): fulfilled, rejected, pending.

          Promise 的優(yōu)點:

          1. 一旦狀態(tài)改變,就不會再變,任何時候都可以得到這個結(jié)果
          2. 可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調(diào)函數(shù)

          Promise 的缺點:

          1. 無法取消 Promise
          2. 當處于pending狀態(tài)時,無法得知目前進展到哪一個階段

          28. Promise構(gòu)造函數(shù)是同步還是異步執(zhí)行,then中的方法呢 ?promise如何實現(xiàn)then處理 ?

          Promise的構(gòu)造函數(shù)是同步執(zhí)行的。then 中的方法是異步執(zhí)行的。


          29. Promise和setTimeout的區(qū)別 ?

          Promise 是微任務(wù),setTimeout 是宏任務(wù),同一個事件循環(huán)中,promise.then總是先于 setTimeout 執(zhí)行。


          30. 如何實現(xiàn) Promise.all ?

          要實現(xiàn) Promise.all,首先我們需要知道 Promise.all 的功能:

          1. 如果傳入的參數(shù)是一個空的可迭代對象,那么此promise對象回調(diào)完成(resolve),只有此情況,是同步執(zhí)行的,其它都是異步返回的。
          2. 如果傳入的參數(shù)不包含任何 promise,則返回一個異步完成. promises 中所有的promise都“完成”時或參數(shù)中不包含 promise 時回調(diào)完成。
          3. 如果參數(shù)中有一個promise失敗,那么Promise.all返回的promise對象失敗
          4. 在任何情況下,Promise.all 返回的 promise 的完成狀態(tài)的結(jié)果都是一個數(shù)組
          Promise.all = function (promises) {
           return new Promise((resolve, reject) => {
           let index = 0;
           let result = [];
           if (promises.length === 0) {
           resolve(result);
           } else {
           function processValue(i, data) {
           result[i] = data;
           if (++index === promises.length) {
           resolve(result);
           }
           }
           for (let i = 0; i < promises.length; i++) {
           //promises[i] 可能是普通值
           Promise.resolve(promises[i]).then((data) => {
           processValue(i, data);
           }, (err) => {
           reject(err);
           return;
           });
           }
           }
           });
          }
          


          31.如何實現(xiàn) Promise.finally ?

          不管成功還是失敗,都會走到finally中,并且finally之后,還可以繼續(xù)then。并且會將值原封不動的傳遞給后面的then.

          Promise.prototype.finally = function (callback) {
           return this.then((value) => {
           return Promise.resolve(callback()).then(() => {
           return value;
           });
           }, (err) => {
           return Promise.resolve(callback()).then(() => {
           throw err;
           });
           });
          }
          

          32. 什么是函數(shù)柯里化?實現(xiàn) sum(1)(2)(3) 返回結(jié)果是1,2,3之和。

          函數(shù)柯里化是把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的函數(shù),并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。

          function sum(a) {
           return function(b) {
           return function(c) {
           return a+b+c;
           }
           }
          }
          console.log(sum(1)(2)(3)); // 6
          

          引申:實現(xiàn)一個curry函數(shù),將普通函數(shù)進行柯里化:

          .我們可以在下列哪個 HTML 元素中放置 Javascript 代碼?()

          A.<script>

          B.<javascript>

          C.<js>

          D.<scripting>

          2.寫 "Hello World" 的正確 Javascript 語法是?()

          A.("Hello World")

          B."Hello World"

          C.response.write("Hello World")

          D.document.write("Hello World")

          3.插入 Javacript 的正確位置是?()

          A.<body>部分

          B.<head>部分

          C.<body>部分和<head>部分均可

          4.引用名為 "xxx.js" 的外部腳本的正確語法是?()

          A.<script src="xxx.js">

          B.<script href="xxx.js">

          C.<script name="xxx.js">

          5.如何在警告框中寫入 "Hello World"?()

          A.alertBox="Hello World"

          B.msgBox("Hello World")

          C.alert("Hello World")

          D.alertBox("Hello World")

          6.如何創(chuàng)建函數(shù)?()

          A.function:myFunction()

          B.function myFunction()

          C.function=myFunction()

          7.如何調(diào)用名為 "myFunction" 的函數(shù)?()

          A.call function myFunction

          B.call myFunction()

          C.myFunction()

          8.如何編寫當 i 等于 5 時執(zhí)行一些語句的條件語句?()

          A.if (i==5)

          B.if i=5 then

          C.if i=5

          D.if i==5 then

          9.如何編寫當 i 不等于 5 時執(zhí)行一些語句的條件語句?()

          A.if =! 5 then

          B.if >< 5

          C.if (i >< 5)

          D.if (i != 5)

          10.在 JavaScript 中,有多少種不同類型的循環(huán)?()

          A.兩種。for 循環(huán)和 while 循環(huán)。

          B.四種。for 循環(huán)、while 循環(huán)、do...while 循環(huán)以及 loop...until 循環(huán)。

          C.一種。for 循環(huán)。

          11.for 循環(huán)如何開始?()

          A.for (i <= 5; i++)

          B.for (i = 0; i <= 5; i++)

          C.for (i = 0; i <= 5)

          D.for i = 1 to 5

          12.如何在 JavaScript 中添加注釋?()

          A.' This is a comment

          B.<!--This is a comment-->

          C.//This is a comment

          13.可插入多行注釋的 JavaScript 語法是?()

          A./*This comment has more than one line*/

          B.//This comment has more than one line//

          C.<!--This comment has more than one line-->

          14.定義 JavaScript 數(shù)組的正確方法是?()

          A.var txt = new Array="George","John","Thomas"

          B.var txt = new Array(1:"George",2:"John",3:"Thomas")

          C.var txt = new Array("George","John","Thomas")

          D.var txt = new Array:1=("George")2=("John")3=("Thomas")


          15.如何把 7.25 四舍五入為最接近的整數(shù)?()

          A.round(7.25)

          B.rnd(7.25)

          C.Math.rnd(7.25)

          D.Math.round(7.25)

          16.如何求得 2 和 4 中最大的數(shù)?()

          A.Math.ceil(2,4)

          B.Math.max(2,4)

          C.ceil(2,4)

          D.top(2,4)

          17.打開名為 "window2" 的新窗口的 JavaScript 語法是?()

          A.open.new("http://www.w3cschool.cn","window2")

          B.new.window("http://www.w3cschool.cn","window2")

          C.new("http://www.w3cschool.cn","window2")

          D.window.open("http://www.w3cschool.cn","window2")


          18.如何在瀏覽器的狀態(tài)欄放入一條消息?()

          A.statusbar = "put your message here"

          B.window.status = "put your message here"

          C.window.status("put your message here")

          D.status("put your message here")

          19.如何獲得客戶端瀏覽器的名稱?()

          A.client.navName

          B.navigator.appName

          C.browser.name

          20.外部腳本必須包含 <script> 標簽。()

          A.正確

          B.錯誤

          請把你的答案寫在留言區(qū)。^_^


          主站蜘蛛池模板: 日韩熟女精品一区二区三区| 国产伦精品一区二区三区不卡| 亚洲无删减国产精品一区| 亚洲色精品aⅴ一区区三区| 亚洲国产精品无码第一区二区三区| 精品一区二区三区在线播放| 怡红院一区二区三区| 无码人妻一区二区三区一| 久久精品免费一区二区三区| 少妇人妻偷人精品一区二区| 国产综合视频在线观看一区| 亚洲AV无码一区二区一二区| 午夜福利一区二区三区在线观看 | 波多野结衣电影区一区二区三区| 国产一区二区三区久久精品| 中文字幕一区二区三区在线播放| 国产乱人伦精品一区二区| 欧洲精品无码一区二区三区在线播放| 成人无码一区二区三区| 精品永久久福利一区二区| 国产一区二区在线观看麻豆| 精品人体无码一区二区三区| 无码人妻视频一区二区三区| 一区二区三区四区无限乱码| 亚洲A∨无码一区二区三区| 免费无码VA一区二区三区| 亚洲中文字幕无码一区二区三区 | 男插女高潮一区二区| 精品国产一区二区三区在线| 亚洲综合av一区二区三区| 99精品国产高清一区二区| 亚洲国产一区视频| 在线|一区二区三区| 久久人做人爽一区二区三区| 无人码一区二区三区视频| 日本精品视频一区二区| 国模一区二区三区| 亚洲午夜精品一区二区麻豆| 久久久精品人妻一区二区三区蜜桃| 天堂不卡一区二区视频在线观看| 国模大胆一区二区三区|