前端面試題

進程和線程的區別?

1.對操做系統來講,一個任務就是一個進程,如打開一個瀏覽器、記事本;線程存在在進程內部。javascript

2.同一個進程能夠包括多個線程,而且線程共享整個進程的資源(寄存器、堆棧、上下文),一個進程至少包括一個線程)php

死鎖是什麼?產生的緣由?必要條件?怎麼處理?

1.相互等待資源所產生的一種僵持狀態,若是沒有外力干預將一直保持這個狀態。css

2.系統資源不足、相互爭搶資源、資源請求順序不當html

3.互斥、不可搶佔、循環等待、請求與保持前端

4.互斥是不可改變的,因此只能破壞其餘三個條件中的一個來解除死鎖,方法:剝奪資源、殺死其中一個線程html5

什麼是HTML語義化?

根據內容使代碼結構化,選擇合適的標籤能使代碼語義化,便於開發者閱讀和寫出更優雅的代碼,同時也讓瀏覽器的爬蟲和機器更好地解析java

爲何要語義化?

  • 爲了在沒有CSS的狀況下也能呈現出很好的內容結構es6

  • 用戶體驗更好,如title解釋名詞信息,alt解釋圖片信息ajax

  • 有利於SEO(search engine optimization):和搜索引擎創建良好的溝通,有利於爬蟲抓取更多信息:爬蟲依賴標籤來肯定上下文和各個關鍵字的權重json

  • 方便其餘設備解析(屏幕閱讀器、盲人閱讀器、移動設備)

  • 便於團隊開發維護

寫代碼時要注意什麼?

  • 儘量減小無語義標籤的使用,如div和span

  • 語義不明顯時,若是能夠用div或p,儘可能用p,它默認有上下間距,對兼容特殊終端有利

  • 不要用純樣式標籤,如b,font,u等

  • 須要強調的文本,能夠包含在strong(加粗)或者em(斜體)中

  • 使用表格時,標題用caption,表頭用thead,主體部分用tbody包圍,尾部用tfoot包圍。表頭和通常單元格要區分開,表頭用th,單元格用td

  • 表單域要用fieldset標籤包起來,並用legend標籤說明表單的用途

  • 每一個input標籤對應的文本都用label標籤,並經過爲input設置id屬性,在label中設置for=someid讓說明文本和對應的input關聯起來

HTML5新增的語義標籤

header

footer

hgroup

nav

aside

section

article

行內元素有哪些?

a b(粗體) span img input strong select label em button textarea

塊級元素有哪些?

div ul li dl(定義列表) dt(列表中的項目) dd(描述列表中的項目) p h1-h6 blockquote

空元素有哪些?

br meta hr(水平線分隔) link input img

inline、block、inline-block的區別?

inline:和其餘元素都在一行上,高、行高及頂和底邊距不可變,寬度就是其文字或圖片的寬度,不可改變

block:總在新行上開始,高度,行高,及頂和底邊距均可變,寬度缺省是它容器的100%,除非設定一個寬度

inline-block:將對象呈現爲內聯對象,可是對象的內容做爲塊對象呈現,塊對象在一行內呈現,容許空格,能夠設置塊元素寬度和高度

inline和inline-block之間產生空隙的緣由

由於標籤段之間的空格

移除空格的方法

  1. 去掉HTML中的空格

  2. 使用margin負值,這個負值的大小與上下文的字體和文字大小相關,大約在3-4像素之間

  3. 只在最後一個a標籤後加上</a>(兼容IE),在HTML5直接不加結束標籤

  4. 使用font-size:0

  5. 使用letter-spacing(字符間距)、word-spacing(單詞間距)

     

position的取值

static:默認值,對象遵循常規流

relative:對象遵循常規流,並參照自身在常規流中經過top、right、bottom、left這4個定位偏移屬性進行偏移時不會影響常規流中的任何元素

absolute:對象脫離常規流,此時偏移屬性參照的是離自身最近的定位祖先元素,若是沒有定位的祖先元素,則一直回溯到body元素。盒子的偏移位置不影響常規流中的任何元素,其中margin不與其餘任何margin摺疊

fixed:與absolute一致,但偏移定位是以窗口爲參考。當出現滾動條時,對象不會隨着滾動

center:與absolute一致,但偏移定位是以定位祖先元素的中心點爲參考,盒子在其包含容器內水平居中(CSS3)

清除浮動的方法?

1.父級div定義height

  • 原理:父級div手動定義height,解決了父級div沒法自動取得高度的問題

  • 優勢:簡單,代碼少

  • 缺點:只適合高度固定的佈局,要給出精確的高度

2.在結尾加一個空div標籤,style="clear:both"

  • 原理:添加一個空div,利用css的clear:both清除浮動,讓父級div能自動獲取高度

  • 優勢:簡單,代碼少,瀏覽器支持好

  • 缺點:若是頁面浮動佈局過多,就要增長不少空div,不建議使用

3.父級div定義,僞類:after和zoom(IE專有屬性,解決IE6,7浮動問題)

father:after{display:block;clear:both;content:"";visibility:hidden;height:0}
father{zoom:1}
  • 優勢:瀏覽器支持好

  • 缺點:代碼多

4.父級div定義 overflow:hidden

  • 原理:必須定義width,同時不能定義height,使用overflow:hidden時,瀏覽器會自動檢查浮動區域的高度

  • 優勢:簡單代碼少,瀏覽器支持好

  • 缺點:不能和position配合使用,由於超出的尺寸會被隱藏

5.父級定義 overflow:auto

  • 原理同上

  • 優勢:簡單,瀏覽器支持好

  • 缺點:內部寬高超過父級div時,會出現滾動條

BFC

定義:(Block formatting context)塊級格式化上下文,是一個獨立的渲染區域,只有Block-level box參與,它規定了內部的Block-level Box如何佈局,而且與這個區域外部絕不相干

BFC佈局規則

  • 內部的Box會在垂直方向,一個接一個地放置

  • box垂直方向的距離有margin決定。屬於同一個BFC的兩個相鄰的box的margin會發生重疊

  • 每一個元素的margin box的左邊,與包含快border box的左邊相接觸,即便存在浮動也是如此

  • BFC的區域不會與float box重疊

  • BFC就是一個獨立的隔離的容器,容器裏面的子元素不會影響到外面的元素,反之也如此

  • 計算BFC高度時,浮動元素也參與運算

哪些元素會產生BFC

  • 根元素

  • float屬性不爲none

  • position爲absolute或者fixed

  • display屬性爲inline-block、table-cell、table-caption、flex、inline-flex

  • overflow不爲visible

盒模型

盒模型分爲IE盒模型和W3C標準盒模型

1.W3C盒模型:width,height只包含content,不包含border和padding

2.IE盒模型:width,height包含border和padding,指的是content+padding+border

在IE8+的瀏覽器中能夠設置box-sizing控制,默認值爲content-box,若是設爲border-box則用的是IE盒模型

Transform/transition/animation

transform:一個靜態屬性,一旦寫到style裏面會直接顯示做用,無任何變化過程

transform/animation:這兩個屬性實現的功能都是同樣的,經過控制屬性變化的過程,實現動畫,都是立足於控制自己dom和css屬性變化過程,來實現動畫的視覺效果;區別在於,二者的控制力度不同,transition更加粗糙一點,對過渡的速度進行了封裝,能夠控制是勻速改變仍是貝塞爾曲線等,而animation指定的keyframe方法,能夠手動去指定每一個階段的屬性,此外還有循環次數、動畫延遲等功能,更加自由強大

padding/margin使用百分比單位

這種狀況下都是根據最近的父級容器的寬度width進行計算的

使用百分比單位的目的:彌補元素高度沒法自適應地與元素寬度保持一致的缺陷

css元素權重

  1. 內聯樣式表的權值最高 1000。

  2. ID 選擇器的權值爲 100。

  3. Class 類選擇器的權值爲 10。

  4. HTML 標籤(類型)選擇器的權值爲 1。

  5. 屬性選擇器的權重爲10

  6. 通配符權重爲0

  7. 僞類選擇器權重爲10

  8. 僞元素選擇器權重爲1

 

JavaScript數據類型

一共7種:字符串、數字、布爾值、數組、對象、Null、Undefined

this的指向問題

this:在執行上下文建立時肯定的一個在執行過程當中不可更改的變量

this只在函數調用階段肯定,也就是執行上下文建立的階段進行賦值,保存在變量對象中,因此也致使了this的多變性,函數在不一樣的調用方式下均可能致使this的值不一樣

可是this的指向在嚴格模式下和非嚴格模式下有所不一樣。當函數獨立調用時,嚴格模式下this指向undefined,非嚴格模式下,當this指向undefined時,自動指向全局對象(瀏覽器中就是window)

當一個對象在全局聲明時,對象內部屬性中的this指向全局對象,當對象在一個函數中聲明時,嚴格模式下this會指向undefined,非嚴格模式下轉爲指向全局對象

函數的調用方式

  • 在全局環境或是普通函數中直接調用

 1 var a = 1;
 2 var obj = {
 3     a:2,
 4     b:function (){
 5         function fun(){
 6             return this.a
 7         }
 8         console.log(fun());
 9     }
10 }
11 obj.b();//1

 

 

  • 做爲對象的方法

1 var a = 1;
2 var obj = {
3     a:2,
4     b:function() {
5         return this.a
6     }
7 }
8 console.log(obj.b())//2

 

b所引用的匿名函數做爲obj的一個方法調用,這時候this指向調用它的對象,這裏也就是obj

那麼不做爲對象的方法調用是什麼意思呢?

1 var a = 1;
2 var obj = {
3     a:2,
4     b:function(){
5         return this.a;
6     }
7 }
8 var t = obj.b;
9 console.log(t());//1

 

這裏的t應該理解爲指向b屬性的指針

  • 使用apply或者call

  • 做爲構造函數

構造函數:經過new關鍵字批量生產咱們須要的對象的函數,如FUNCTION、object、Array、Date等全局定義的構造函數,注意,構造函數首字母要大寫

 1 function Category(){
 2     this.name = 'annika';
 3     this.school = 'college';
 4     this.height = '160';
 5     this.run = function(){
 6         return this.name + '正在跑步';
 7     }
 8 }
 9 Fun.prototype = {
10     constructor:Fun,
11     say: function(){
12         return this.name + '正在說話';
13     }
14 }
15 var f = new Fun();
16 f.run();  //annika正在跑步
17 f.say();  //annika正在說話

 

若是函數做爲構造函數用,那麼其中的this就表明它即將new出來的對象

new作了以下的事

  • 建立一個臨時對象

  • 給臨時對象綁定原型

  • 給臨時對象對應的屬性複製

  • 將臨時對象返回

箭頭函數

箭頭函數不能夠用call和apply改變this

 1 var a = 1;
 2 var obj = {
 3     a:2
 4 };
 5 var fun = () => console.log(this.a);
 6 fun(); //1
 7 fun.call(obj); //1
 8 var a = 1;
 9 var obj={
10     a:2
11 };
12 function fun(){
13     var a = 3;
14     let f = () => console.log(this.a);
15     fun();
16 }
17 fun();//1
18 fun.call(obj);//2

 

注意,此時fun的上下文就是箭頭函數所在的上下文,所以此時的f的this爲fun的this,也就是window,當fun.call(obj)再次調用時,新的上下文被建立,fun此時的this爲obj,也就是箭頭函數的this值

1 function Fun(){
2     this.name = 'annika';
3 }
4 Fun.prototype.say = () => {
5     console.log(this);
6 }
7 var f = new Fun();
8 f.say(); //window

 

此時箭頭函數所在的上下文是__proto__所在的上下文也就是Object函數的上下文,而object的this值就是全局對象

1 function Fun(){
2     this.name = 'annika'
3     this.say = () => {
4         console.log(this);
5     }
6 }
7 var f = new Fun();
8 f.say(); //Fun的實例對象

 

此時箭頭函數所在的上下文變成了Fun的上下文環境,由於當函數做爲構造函數調用的時候,上下文環境的this指向實例對象

做用域和做用域鏈

變量的做用域分爲兩種:全局變量和局部變量

全局做用域:最外層定義的變量擁有全局做用域,對於其內部函數來講,都是能夠訪問的

局部做用域:通常只在固定的代碼片斷內能夠訪問到,對於函數外部是沒法訪問的,最多見的例如函數內部

做用域鏈:內部函數能夠訪問外部函數變量的機制,用鏈式查找決定哪些數據能被內部函數訪問。

執行環境(execution context):每一個函數運行時都會產生一個執行環境js爲每個執行環境關聯了一個變量對象。環境中定義的全部變量和函數都保存在這個對象中。

全局執行環是最外圍的執行環境,被認爲是window對象,所以全部的全局變量和函數都是做爲window的屬性和方法建立的。

js的執行順序是根據函數的調用來決定的,當一個函數被調用時,該函數環境的變量對象就被壓入一個環境棧中,而在函數執行以後,棧將該函數的變量對象彈出,把控制權交給以前的執行環境變量對象

當某個函數第一次被調用時,就會建立一個執行環境,及相應的做用域鏈,並把做用域鏈賦值給一個特殊的內部屬性[scope]。而後用this,arguments和其餘的命名參數的值來初始化函數的活動對象。當前執行環境的變量對象始終在做用域鏈的第0位。

標識符解析是沿着做用域鏈一級一級地搜索標識符的過程。搜索過程始終從做用域鏈的前端開始,而後逐級向後回溯,直到找到標識符爲止

閉包

定義:一種內部函數的做用域鏈依然保持着對父函數活動對象的引用的函數

做用:

  • 能夠讀取自身函數外部的變量(沿着做用域鏈查找)

  • 可讓這些外部變量始終保存在內存之中

缺點:

1.因爲閉包會使得函數中的變量都保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題,在IE中可能致使內存泄漏,解決方法是,在退出函數以前,將不使用的局部變臉所有刪除

2.閉包會在父函數外部,改變父函數內部變量的值。

原型與原型鏈

函數的原型對象:在js中,咱們在聲明一個函數的時候,瀏覽器的內存中會建立一個對象B,並且並且每一個函數都默認會有一個屬性prototype指向了這個對象,這個B就是函數A的原型對象,簡稱函數的原型。這個原型對象B默認會有一個屬性constructor指向這個函數A。原型對象默認只有屬性:constructor。其餘都是從Object繼承而來

使用構造函數建立對象:把一個函數做爲構造函數,使用new建立對象的時候,那麼這個對象就會存在一個默認的不可見的屬性,來指向了構造函數的原型對象。這個不可見的屬性通常用[[prototype]]來表示,只是這個屬性沒有辦法直接訪問到

與原型有關的幾個屬性和方法

1.constructor屬性:存在於原型對象中,它指向構造函數。咱們有時候能夠根據prototype屬性,來修改原來的原型對象,可是通過修改,原型對象會失去對原來的constructor的指針,此時能夠手動再綁定回去

2.__proto__屬性:個別瀏覽器提供了對[[prototype]]的訪問方法,就是這個屬性,這個是對象的屬性,可是儘可能不要用這種方法訪問,他有可能改變這個對象的繼承原型鏈

3.hasOwnProperty()方法

用來判斷一個屬性是來自對象自己,仍是來源於其所在的原型鏈。注意只能判斷是否是來自對象,不能判斷原型中存不存在,由於無論存不存在都會返回false

4.in操做符

用來判斷一個屬性是否存在於這個對象中。可是在查找這個屬性的時候,先在對象自身中找,若是對象找不到,再到原型中去找。只要對象和原型中有一個地方存在這個屬性,就返回true

原型建立對象的缺陷:由於原型中的全部屬性都是共享的,因此若是對一個對象的原型的屬性作了修改,會反應到全部的對象上面。這個共享的形式對屬性值是函數的屬性很方便

構造函數模型建立對象的缺陷:構造函數中的全部屬性和方法,每一個對象獨有,不會共享,可是對方法又不太合適,由於有時只須要一個方法

組合模式解決缺陷:基於以上兩臺產生了組合模式,原型模式適合封裝方法,構造函數模式適合封裝屬性,綜合兩種模式的優勢就有了組合模式

動態原型模式建立對象:組合模式有一點不完美,就是把構造方法和原型分開寫,讓人感受不舒服,因此應該想辦法把構造方法和原型封裝在一塊兒,因此有了動態原型模式。動態原型模式把全部的屬性和方法都封裝在構造方法中,僅在須要的時候纔去構造方法中初始化原型,又保持了原型和構造函數的優勢。

 1 function(name,age){
 2     this.name = name;
 3     this.age = age;
 4     if(typeof this.eat !== "function"){
 5         Person.prototype.eat = function(){
 6             return(this.name + 'eating')
 7         }
 8     }
 9 }
10 var p1 = new Person('annika',21);
11 p1.eat();

 

宏任務與微任務

  • 宏任務按順序執行,且瀏覽器在每一個宏任務之間渲染頁面

  • 全部的微任務也按順序執行,且在如下場景會當即執行全部微任務

    • 每一個回調以後,且js執行棧中爲空

    • 每一個宏任務結束以後

跨域問題

  • 爲何會出現跨域問題

    • 處於瀏覽器的同源策略限制,瀏覽器會拒絕跨域請求,但不是全部的跨域都會被拒絕,有以下三種狀況:

      • 一般瀏覽器容許跨域寫操做(cross-site writes),如連接、重定向

      • 一般容許跨域資源嵌入(cross-site embedding),如img,script

      • 一般瀏覽器不容許跨域讀操做(cross-site reads)

  • 什麼狀況算做跨域

    • 非同源請求,同源——兩個頁面擁有相同的協議(protocol),端口(port)和主機(host),那麼這兩個頁面就屬於同一個源(origin)

  • 爲何有跨域需求

    • 工程服務化之後,不一樣職責額服務分散在不一樣的工程中,每每這些工程的域名是不一樣的,一個需求可能對應多個服務,這是就須要使用不一樣的服務接口,所以會出現跨域

  • 如何實現跨域

    • 最經常使用的跨域方式有三種:JSONP、CORS、postMessage

    • JSONP

      • 實現原理:雖然不能經過XHR請求不一樣域上的數據,可是在頁面上引入不一樣域的js腳本是能夠的,在js文件載入完畢後,觸發回調,能夠將須要的data做爲參數傳入

      • 實現方式(需先後端配合)

         1 <script type="text/javascript">
         2     function dosomething(data){
         3         //處理得到的數據
         4     }
         5 </script>
         6 <script src="http://example.com/data.php?callback=dosomething"></script>
         7 <?php
         8 $callback = $_GET['callback'];//獲得回調函數名
         9 $data = array('a','b','c');//要返回的數據
        10 echo $callback.'('.json_encode($data).')';//輸出
        11 ?>

         

      • 優缺點

        優勢:兼容性好

        缺點:1.JSONP只支持GET請求;2.XMLHTTPRequest相對於JSONP有更好地錯誤處理機制

    • CORS(cross-origin resource sharing )跨域源資源共享

      • 基本思想:使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功仍是失敗。

      • IE實現

        1 var xdr = new XDomainRequest();
        2 xdr.onload = function(){
        3     alert(xdr.responseText);
        4 }
        5 xdr.open("get","http://www.somewhere-else.com/page/");
        6 xdr.send(null);

         

      • 其餘瀏覽器:原生支持CORS

         1 var xhr = createXHR();
         2 xhr.onreadyStatechange = function(){
         3     if(xhr.readyState == 4){
         4         if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
         5             alert(xhr.responseText);
         6         } else{
         7             alert("Request was unsuccessful:" + xhr.status);
         8         }
         9     }
        10 };
        11 xhr.open("get","http://www.somewhere-else.com/page/",true);
        12 xhr.send(null);

         

    • postMessage

      • window.postMessage(message,targetOrigin)方法是html5新引進的特性,能夠用它來向其餘window對象發送信息,不管同源不一樣源

        1 otherWindow.postMessage(message,targetOrigin,[transfer]);

         

         

前端攻擊

  • XSS攻擊

深拷貝和淺拷貝

  • 主要區別:在內存中的儲存類型不一樣

    棧是自動分配的內存空間,它由系統自動釋放,而堆是動態分配的內存,大小不定,也不會自動釋放

  • 基本數據類型(boolean/number/string/undefined/null)存放在棧中,是直接按值存放的,能夠直接訪問,且基本數據類型的值不可變,基本類型的比較是值得比較,只要值相等就認爲其相等

  • 引用類型(object)存放在堆中,變量其實是一個存放在棧內存的指針,這個指針指向堆內存中的地址。每一個空間大小不同,要根據狀況進行特定的分配。引用類型的值可變,引用類型的比較是引用的比較,看其引用是否指向同一個對象

  • 傳值與傳址:基本數據類型的賦值是在內存中新開闢一段棧內存,而後再把值賦到新的棧中,因此兩個變量相互獨立不影響;引用類型的賦值是傳址,只是改變指針的指向,也就是說引用類型的賦值是對象保存在棧中的地址的賦值,兩個變量指向同一個對象,所以二者之間操做相互有影響

  • 淺拷貝只複製一層對象的屬性,並不包括對象裏面的爲引用類型的數據。

  • 深拷貝是對對象及全部的子對象進行拷貝

ajax的過程

0:未初始化,還沒有調用open方法

1:啓動,已經調用open方法,但還沒有調用send方法

2:發送,已經調用send方法,可是還沒有收到響應

3:接收,已經收到部分響應數據

4:完成,已經接收到所有響應數據,能夠在客戶端使用了

 1 //建立XMLHttpRequest對象
 2 var xmlhttp = null;
 3 if(window.XMLHttpRequest)
 4 {
 5     xmlhttp = new XMLHttpRequest();
 6 }
 7 else if(window.ActiveXObject)
 8 {
 9     xmlhttp = new ActiveXobject("Microsoft.XMLHTTP");
10 }
11 12 if(xmlhttp != null)
13 {
14     //指定響應函數
15     xmlhttp.onreadyStatechange=State_change;
16     //打開鏈接(指定請求)
17     xmlhttp.open("GET","/example/note.xml",true);
18     //發送請求
19     xmlhttp.send(null)
20 }
21 22 //建立響應函數
23 function State_change()
24 {
25     if(xmlhttp.readyState == 4)
26     {
27         if(xmlhttp.status == 200)
28         {
29             //具體邏輯
30         }
31     }
32     else
33     {
34         alert("error");
35     }
36 }

 

es6新特性

  • let和const

  • 變量的解構賦值

  • 箭頭函數

  • Set和Map結構

  • Iterator和for..of循環

  • Generator函數

  • promise對象

    • 三個狀態(resolve/reject/pending)

    • async函數

      • Genarator函數的語法糖

      • 優勢在於內置執行器,擁有更好地語義和更廣的適用性

  • class

事件捕獲和事件冒泡

事件冒泡:先觸發子元素的處理器,再觸發父元素的事件處理器,每向上走一層都會檢查這一層有沒有事件處理器,若是有就觸發,若是沒有就繼續向上查找,直到頂層body

事件捕獲:從body向下找,若是父級元素有事件處理器就先觸發父級元素,再向下一層,直到這個點擊位置的最底層,也就是target

DOM2級事件流總共分爲三個階段:事件捕獲、在目標元素上、事件冒泡

兩個方法:addEventListener()和removeEventListener(),接受三個參數:事件名稱、事件處理器,和布爾值,布爾值默認爲false,表明事件處理器在冒泡階段觸發,true表明在捕獲階段觸發

Dom0級事件只能在冒泡階段觸發

若是要一次性註冊多個事件:

  • 對於非target節點先執行捕獲再執行冒泡

  • 對於target節點先執行先註冊事件

處理事件代理時,event有兩個特殊屬性,event.target和event.currentTargret,前者是事件觸發元素,後者是事件綁定元素,大部分狀況下,在使用事件代理時,event.target是子元素,event.currentTarget是父元素

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息