記錄前端的面試日常(持續更新)


寫在前面的話

又到了跳槽的季節,現在也該總結一下自己在前端積累這么多年的一點珍藏的貨色了,注意了我主要總結是盡量用自己能表達的想法去說,所有可能沒別人總結的那么客觀,還有盡量用簡短的話簡單的思路去表達應該有的意思,方便記憶理解,還有這篇博文我會持續更新的

什么叫優雅降級和漸進增強(這個其實很多的,但是我是不可能去背的,所有盡量用少的話,總結清楚)

.transition{
  -webkit-transition: all .5s;
     -moz-transition: all .5s;
       -o-transition: all .5s;
          transition: all .5s;  
}//漸進增強
.transition{ 
     transition: all .5s;
  -o-transition: all .5s;
  -moz-transition: all .5s;
-webkit-transition: all .5s;
}//優雅降級

優雅降級:一開始就構建完整的功能,然后再針對低版本瀏覽器進行兼容

漸進增強:針對低版本瀏覽器進行構建頁面,保證最基本的功能,然后再針對高級瀏覽器進行效果.交互等改進和追加功能達到最好的用戶體驗

jQuery的實現原理

(functon(window,undefined){})(window)

jQuery利用JS函數作用域的特性,采用立即調用表達式包裹了自身,解決命名空間和變量污染問題

window.jQuery=window.$=jQuery

在閉包當中將jQuery和$()綁定到window上,從而jQuery和$暴露為全局變量

jQuery.fn的init方法返回的this就是jQuery對象

核心是對DOM 操作進行的封裝,以避免單獨實現不同瀏覽器的兼容代碼

通過代理對象,給不同的對象監聽事件,進行管理

jQuery 的屬性拷貝(extend)的實現原理是什么,如何實現深拷貝?

淺拷貝(只復制一份原始對象的引用)

  • var newObject=$.extend({},oldObject)

深拷貝(對原始對象實行所引用的對象進行遞歸拷貝)

JSON對象parse方法可以將JSON字符串反序列化成js對象,stringify方法可以將js對象序列化成json字符串,這兩種方法產生一個便捷的深克隆

  • var newObject=$.extend(true,{},oldObject)

深淺拷貝的區別

深拷貝之后,改變其中一個值,不會影響另外一個值,淺拷貝則會影響

淺拷貝只是拷貝了指向對象的指針

而深拷貝則是完全拷貝整個值,創建了一個新的和原對象一樣的對象

清除浮動

第一種overflow:hidden

第二種

.clearfix:after{
  content:".",
  diplay:block;
  hieght:0;
  clear:both;
  visibility:hidden;
}

最快速的數組求最大值

var arr=[1,2,12,5,6];

Math.max(...arr);//es6

math.max.apply(null,arr)//es5 apply

//for循環
let max=arr[0];
for(let i=0;i<arr.length-1;i++){
  max=arr[i]<arr[i+1]?arr[i+1]:arr[i]
}

//數組sort()
arr.sort((num1,num2)=>{return num1-num2<0})//回憶a-b升序b-a降序,同理喔
arr[0]

//數組reduce
//這個還是需要科普一下
//aray的reduce()把一個函數作用在整個Array的[x1,x2,x3,x4...]上,這個必須接受兩個
//參數,reduce()把結果繼續和序列的下一個元素做累計計算,怎么感覺有點像map
//感覺沒有解釋清楚,下面給個地址
arr.reduce((num1,num2){return num1>num2?num1:num2})

reduce科普

數組去重

[... new Set([2,"23","2","5",12,5,6,12])]最快速的方式

  • 最簡單的方法
  function arr1(){
    var n=[];
    for(var i=0;i<arr.length;i++){
    	if(n.indexOf(arr[i])==-1){
    		n.push(arr[i])
    	}
    }
    return n;
  }

cookie是網站為了標識用戶身份而存儲在用戶本地終端上的數據

cookie數據使用在同源的http請求中攜帶,會在瀏覽器和服務器來回傳遞

webStorage目的:克服cookie帶來的一些限制,當數據需要被嚴格控制在客戶端是,不需要持續的將數據發回服務器

webstorage提供兩種API:localstorage(本地存儲)和sessionStorage(會話存儲)

生命周期:

  • localStorage(本地存儲)

    - 永久的,關閉網頁也不會消失,除非主動刪除數據
    
  • sessionStorage(會話存儲)

    -  數據在當前瀏覽器窗口關閉后自動刪除
    
  • cookie     設置的cookie過期時間之前一直有效,即使瀏覽器關閉

locaStorage(本地存儲)和sessionStorage(會話存儲)不會自動把數據發給服務器,僅僅本地保存

存儲大小:

  • cookie -->4k
  • sessionStorage和localStorage -->5m或更大

javascript有幾種類型的值

:原始數據類型(undefined,null,Boolean,number,string)

:引用數據類型(對象,數組,函數)

區別:存儲位置不同

原始類型數據直接存儲在棧的簡單數據段

  • 占據空間小,大小固定,屬於被平凡使用數據,所以放在棧中存儲

引用數據類型存儲在堆中的對象

  • 占據空間大,大小不固定,如果存儲在棧中,將會影響程序運行的性能
  • 引用數據類型在棧中存儲了指針,該指針指向該實體的起始地址
  • 當解釋器尋找引用值時,會首先檢索在棧中的地址,取得地址后從堆中獲取實體

javascript如何實現繼承

原型prototype機制或apply和call方法去實現較簡單,建議使用構造函數與原型混合方式。
 
 	function Parent(){
 		this.name = 'wang';
 	}

 	function Child(){
 		this.age = 28;
 	}
 	Child.prototype = new Parent();//繼承了Parent,通過原型

 	var demo = new Child();
 	alert(demo.age);
 	alert(demo.name);//得到被繼承的屬性

什么是doctype

DTD就是告訴瀏覽器我是什么文檔類型,用這個來判斷我用什么來解析它渲染它

doctype就是通知瀏覽器哪個DTD和文檔類型

<!doctypehtml>--->HTML5

HTML4.0有兩個模式:嚴格模式和寬松模式

內核的理解

分為兩個部分:渲染引擎和js引擎

渲染引擎:負責取得網頁的內容(html,css)

js引擎:解析和執行javascript來實現網頁的動態效果,但是后來js引擎越來越獨立了(V8引擎)

有一個長度100的數組,算前10項的和

 var a=[1,2,34,4,5,6,76,7,1,2,3,4,5,6,7]
      sun=null;
      sun=a.slice(0,10).reduce(function(pre,current){
        return pre+current;
      })
      console.log(sun);//reduce可以看前面最大值

javascript優化

松耦合:當修改一個組件而不需要改其他組件時,就做到松耦合

將js從css中抽出,不要使用css表達式

將css從js中抽出:通過js修改css樣式時,使用className或classList

將js從html抽離:從js外置文件

將HTML從js中抽離:不要使用innerHTML使用字符串模板

HTML.css.JS三者的關系應當時相互獨立分離的,如果產生交集,出現緊耦合代碼,就違反了代碼可維護性原則

全局變量

零全局變量(function(){})(window)

單全局變量(jQuery)和命名空間

模塊

事件處理

隔離應用邏輯(將應用邏輯和事件處理的代碼拆分開)

var MyApplication = {
  handleClick: function(event){
    this.showPopup(event);
  },
  showPopup: function(event){
    var popup = document.getElementById('popup');
    popup.style.left = event.clientX + 'px';
    popup.style.top = event.clientY + 'px';
    popup.className = 'reveal';
  }
};
addListener(element,'click',function(event){
  MyApplication.handleClick(event);
});

不要分發事件對象

讓事件處理程序使用event對象來處理事件,然后拿到所有需要的數據傳到應用邏輯

//改進的做法
var MyApplication = {
  handleClick: function(event){
    this.showPopup(event.clientX,event.clientY);
  },
  showPopup: function(x,y){
    var popup = document.getElementById('popup');
    popup.style.left = x + 'px';
    popup.style.top = y + 'px';
    popup.className = 'reveal';
  }
};
addListener(element,'click',function(event){
  MyApplication.handleClick(event);
});

記得在事件處理程序應當在進入應用邏輯之前針對event對象執行任何必要的操作,包括阻止時間冒泡,都應該包含在事件處理程序中

//改進的做法
var MyApplication = {
  handleClick: function(event){
    event.preventDefault();
    event.stopPropagation();
    this.showPopup(event.clientX,event.clientY);
  },
  showPopup: function(x,y){
    var popup = document.getElementById('popup');
    popup.style.left = x + 'px';
    popup.style.top = y + 'px';
    popup.className = 'reveal';
  }
};
addListener(element,'click',function(event){
  MyApplication.handleClick(event);
});

感覺這個需要日積月累,感覺前面是有無數的坑等着你踩先完成功能然后再考慮優化的問題

線程和進程的區別

node進程啟動過后默認會創建一個線程,線程用於執行我們的代碼

一個進程可以有多個線程,所有進程與線程是包含與被包含的關系

進程(程序):一個靜態概念,一個class文件,一個exe文件

線程:是一個程序里面不同的執行路徑

二叉樹遍歷

先序遍歷:順序根左右

中序遍歷:順序左根右

后序遍歷:順序左右根

層序遍歷:順序從上到下從左到右分層遍歷

前序遍歷:先訪問根節點,然后前序遍歷左子樹,再前序遍歷右子樹(中左右)

中序遍歷:從根節點開始(注意不是先訪問根節點),中序遍歷根節點的左子樹,然后是訪問根節點,左后遍歷根節點的右子樹(左中右)

這里還是要多羅嗦一些東西,因為我有時還是有點不太懂(這樣是不是稍微清晰了一點)

中序遍歷:BDCAEHGKF

后序遍歷:從左到右先葉子后節點的方式遍歷訪問根節點(左右中)//怎么有點像css遍歷從上到下從右到左

層序遍歷:從樹的第一層,也就是根節點開始訪問,從上到下逐層遍歷,在同一層中,按從左到右的順序結構訪問

瀏覽器的渲染原理

當瀏覽器獲取html文件時,會"自上而下"加載,並在加載過程解析渲染

解析:

瀏覽器會將HTML解析成一個DOM樹,DOM樹的構建過程是一個深度遍歷過程:當前節點的所有子節點都構建好后才會去構建當前節點的下一個兄弟節點

將CSS解析成CSS Rule Tree

根據DOM樹和CSSOM樹來構造Rendering Treen,注意:Rendering Tree渲染樹並不等同於DOM樹,因為一些想header或display:none的東西就沒必要放在渲染樹中

有了Render Tree,瀏覽器已經能知道網頁中有哪些節點.各個節點的CSS定義以及他們的從屬關系,下一步操作稱之為Layout就是計算出每個節點在屏幕中的位置

然后就進行繪制,遍歷render樹,並使用UI后端層繪制每一個節點

終於說到重點了,影響瀏覽器渲染主要有:reflow(回流)和repaint(重繪)

回流Reflow(渲染機制類)

  • DOM結構中的各個元素都有自己的盒子模型,這些需要瀏覽器根據各種樣式計算並根據計算結果將元素放在該出現的位置,這個過程稱reflow

觸發Reflow

  • 移動DOM

  • 修改CSS

  • 修改網頁默認字體

  • 增加刪除修改DOM節點

重繪Repaint

  • 頁面呈現的內容放在頁面上

觸發Reqaint

  • DOM改動

  • CSS改動

盡量避免reflow(回流)

reflow想想怎么可能避免呢?那只能將reflow對性能的影響減到最小

比如需要改變元素的樣式,不要通過父級元素影響子元素,最好直接加載子元素

設置style屬性改變樣式的話,沒設置一次都會導致一次reflow,最好就是設置class的方式

避免不必要的復雜的css選擇器,尤其是后代選擇器(這里肯定會有人反駁了,我用的是less,就看看解析的時候,后代有多長,看着多怕,哥們要不你用sess或者sass,有個屬性可以直接跳出選擇器@at-rootless有沒有我也不知道)

還有就是不要用tables布局

ES6

從數組中移出falsey值

使用Array.filter()刪選出falsey值(false,null,0,"",undefined和NaN)

const compact=arr=>arr.filter(Boolean);
console.log(compact([0, 1, false, "", 3, "s","e"*23,"a", NaN]));

計算數組中值的出現次數

使用Array.reduce()在每次遇到數組中的特定值時遞增計數器

const coumt=(arr,value)=>arr.reduce((a,v)=>v===value?a+1:a+0,0);
console.log(coumt([12, 1, 1, 2, 3, 4, 32, 2, 1, 1, 1, 1, 1], 1));

如果不理解逗號后面的值,可以再MDN查詢 reduce

深度拼合數組

const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));
console.log(deepFlatten([1, [2], [[3], 4], "a"]));

注意SEO

合理的title,description,keywords:搜索對着三項的權重逐個減小,

語義化的HTML代碼

重要內容HTML代碼放在最前

重要內容不要用js輸出

少用iframe

非修飾性圖片必須加alt

提高網站速度

離線存儲

在線的情況,會請求html的manifest屬性,它會請求manifest文件的內容,根據內容進行離線存儲,讓加載頁面時,會對新的manifest文件內容進行比較,進行存儲

離線的情況,直接使用離線存儲的資源

缺點:

更新的資源,需要二次刷新才會被頁面采用

不支持增量更新,只有manifest發生變化,所有資源全部重新下載一次

缺乏足夠容錯機制,當清單中任意資源文件出現加載異常,都會導致整個manifest策略運行異常

在javascript中一切都是對象嗎?

基本類型: Boolean Null Undefined string number Symbol(E6)

對象類型: Object

  • 數據封裝類對象:Object, Array ,Boolean, Number ,String
  • 其他對象:Function, Arguments ,Math, Date, RegExp,Error
  • 任何非基本類型的都是對象類型

區別

基本類型

  • 不可變,無法添加刪除屬性;按值比較,按值傳遞

對象類型

  • 可變,支持添加刪除屬性,按引用比較,按引用傳遞

檢測對象類型?或者檢測一個數據是數組類型

Object.prototype.toString.call([])

typeof只在基本類型的檢查上面才好使,在引用類型(Function除外) 里面他返回的都是object

Ajax

感覺我會寫好多東西呀,可以當做復習哦,面試的時候說個一二十分鍾不是問題

$.ajax({//jQuery
  url:"http://www.baidu.com",//請求的url地址
  dataType:"json",//返回的數據格式
  data:{} //參數
  type:"GET"
  success:function(data){
    //請求成功的請求
  }
})
  // 1.創建
            var ajax = new XMLHttpRequest();
            // 2設置
            ajax.open('get', 'Ajax_get.php');
            // 3.發送
            ajax.send(null);
            // 4.狀態事件
            ajax.onreadystatechange = function() {
                        if (ajax.readyState == 4 && ajax.status == 200) {
                                    // 5.使用返回的數據 修改頁面的內容
                                    // responseText 返回的就是一個 字符串
                                    // 我們 在ajax 中 如果 是通過 ajax.responseText 獲取到的 統統都是字符串
                                    console.log(ajax.responseText);
                        }
            }
var ajax = new XMLHttpRequest();

		// 使用post請求
		ajax.open('post','ajax_post.php');

		// 如果 使用post發送數據 必須 設置 如下內容
		// 修改了 發送給 服務器的 請求報文的 內容
		// 如果需要像 HTML 表單那樣 POST 數據,請使用 setRequestHeader() 來添加 HTTP 頭。然后在 send() 方法中規定您希望發送的數據:
		ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded");
		// 發送
		// post請求 發送的數據 寫在 send方法中 
		// 格式 name=jack&age=18 字符串的格式
		ajax.send('name=jack&age=998');

		// 注冊事件
		ajax.onreadystatechange = function () {
			if (ajax.readyState==4&&ajax.status==200) {
				console.log(ajax.responseText);
			}
		}
function getXhr() {
        var xhr = null;
        if (window.XHLHttpRequest) {
            xhr = new XMLHttpRequest();
        } else {
            xhr = new ActiveXObect("Microsoft.XMLHttp");
        }
        return xhr;
    }

這個為什么我會單獨寫出來創建的對象兼容因為這里涉及到:
js高階編程技巧之"惰性思想":能夠執行一次就搞定的絕對不會執行多次

Ajax:asyncjavascript and xml 異步的js和XML

客戶端js中的方法,用來向服務器端發送請求(還可以傳遞給服務器端數據,然后把服務器端返回的內容獲取

xml:可擴展的標記語言(在xml文件使用的標簽都是自己擴展的)

利用自己擴展的有規則的標記來存儲相關的數據(xml后台用處很大)

xhr.readyState:請求狀態碼

  • 0 (未初始化)當前的請求還沒有發送

  • 1 (載入)url地址已經打開(發送前的參數配置已經完成)

  • 2(載入完成) 響應頭信息已經接收

  • 3(交互) 主要返回的內容正在服務器端進行准備處理

  • 4(完成) 響應主體的內容已經成功返回到客戶端

xhr.status:HTTP網絡狀態碼,描述了服務器響應內容的狀態

  • 200 表示響應主體的內容已經成功返回了

  • 301->永久重定向/永久轉移

302->臨時重定向/臨時轉移 服務器的負載均衡
304 本次獲取的內容是讀取緩存中的數據
400 客戶端傳遞給服務器端的參數出現錯誤
401 無權限訪問
404 客戶端訪問的地址不存在
500 未知的服務器錯誤

501->服務器已經超負荷 一台服務器能承受10000人,那么第10001個人訪問,如果沒有做服務器的負載均衡,那么這個人的狀態碼就是503

GET和POST的區別

get是從服務器獲取數據----"取";post是向服務器提交數據---"發"

大小問題

  • GET請求傳遞給服務器的內容存在大小限制,而POST理論上沒有限制

  • 原因:GET通過URL傳參給服務器,HTTP協議沒有對URL長度進行限制,但是每個瀏覽器對於URL的長度存在限制,谷歌8k,火狐7kb,IE2kb,如果URL的長度超過限制,瀏覽器會把超出的部分截取

緩存的問題

  • GET請求會出現緩存(這個緩存不一定是304),POST是沒有緩存的

  • 在項目中我們的GET請求一般不會讓其出現緩存"清除緩存":在URL的末尾追加一個隨機數

  • xhr.open("get","/getList?num=12&="+Math.random()")

if (ajax["type"].toLowerCase() === "get") {
//->GET請求還需要在URL的末尾追加隨機數
var suffix = ajax["url"].indexOf("?") > -1 ? "&" : "?";
ajax["url"] += suffix + "_=" + Math.random();
}


安全問題

* 一般來說GET不安全,但是POST相對安全些
var xhr=new XMLHttpRequest();
xhr.open("get", "./vue.html");
xhr.send(null);
xhr.onreadystatechange=function () {
   console.log(xhr.readyState);//沒有任何輸出
   //輸出的2,3,4因為在存儲的時候就已經把0,1已經執行了,也就是說在前面就已經把0,1都已經執行了
   }

垃圾回收機制

js的垃圾回收機制是為了以防止內存泄露,內存泄露的含義就是當已經不需要某塊內存是這塊內存還存在着,垃圾回收機制就是間歇的不定期的尋找不在使用的變量,並釋放掉它們所指向的內存

變量的生命周期

  • 當一個變量的生命周期結束之后它所指向的內存就應該被釋放,JS有兩種變量,全局變量和在函數產生的局部變量,當局部變量的生命周期在函數執行過后就結束了,此時便可被它引用的內存釋放(立即回收),但全局變量生命周期會持續到瀏覽器關閉頁面

回收方式:標記清除.引用技術(不常用)

標記清除

  • 大部分瀏覽器以此方式進行垃圾回收,當變量進入執行環境(函數中聲明變量)的時候,垃圾回收器將其標記為"進入環境",當變量離開環境的時候(函數執行結束)將其標記為"離開環境",在離開環境之后還有的變量則是需要被刪除的變量
  • 垃圾收集器給內存中的所有變量都加上標記,然后去掉環境的變量以及被環境中的變量引用的變量的標記,在此之后再被標記的變量極為需要回收的變量極為需要回收的變量,因為環境中的變量無法訪問到這些變量

引用技術

引用技術的含義就是跟蹤記錄每個值被引用的次數

跨域問題

什么是跨域

只要協議,域名,端口有任何一個不同,就是跨域

為什么不能跨域

瀏覽器的同源策略,用來保護用戶的安全

跨域的解決方案

JSONP

瀏覽器可以引用不同域下的JS文件,利用這個特性,實現跨域

get請求

callback參數

document.domain

頁面地址是http://a.baidu.com,嵌入的iframe是http://b.baidu.com/

分別始終hi頁面和iframe的document.domain為:baidu.com就可以解決

CORS方案

CORS定義一種跨域訪問的機制,可以讓AJAX實現跨域訪問,CORS允許一個域

向另一個域提交跨域的ajax請求

header("Access-Control-Allow-Origin","*")

post請求

反向代理

正向代理代理的對象是客戶端,

反向代理代理的對象是服務器

使用HTML5引進的window.postMessage方法來跨域

個人認為window.name的方法既不復雜也能兼容所有的瀏覽器

HTTP和HTTPS有何差異

HTTP:相對HTTPS來說,速度較快且開銷較小,默認是80端口

HTTPS相對安全但開銷較大(數據以加密的形式傳遞),默認端口443

HTTP是明文跑到TCP上,而HTTPS跑在SSL/TLS應用層之下,TCP上

HTTPS

  • 非對稱加密,生成公鑰和私鑰
  • 更嚴謹的采用CA,給密鑰簽名

變態題

var count = 0;

console.log(typeof count === "number"); // true , 這個不用解釋了

console.log(!!typeof count === "number"); // false

// 這里涉及到就是優先級和布爾值的問題
// typeof count 就是字符串"number"
// !!是轉為布爾值(三目運算符的變種),非空字符串布爾值為 true
// 最后才=== 比較 , true === "number" , return false
(function(){
    var a=b=3;
    //var a,a=b;   b=3跑到全局去了
})()
null instanceof Object       //false  兩個都不熟悉一個數據類型
var val = 'smtg';
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing'); //+的優先級大於等於號

javascript中不容易分清的slice 和splice

slice()

根據索引值和索引值截取字符串(若截取數組,不改變原數組)

slice(1,2) //從第0項開始,包左不包右

slice(-3) //從后往前截取到倒數第三個

slice(5,2)/返回空字符

splice() 截取數組,不能截取字符串

splice(1,2) //改變原數組 ,從0項開始刪除1,2項

splice(1,2,"aaa","bbb") //替換1,2的值

splice(1,0,"aaa","bbb") //在鍵值對為1的前面插入兩個值 ,第二個參數為0就是不替換參數,1就是替換一個參數

jS的閉包

函數聲明的時候,會生成一個獨立的作用域

同一作用域的對象可以互相獨立訪問

作用域呈現包含狀態,形成作用域鏈,子作用域的對象可以訪問父作用域的對象,反之不能;

另外子作用域會使用最近的父作用域的對象

閉包是函數

作為內部函數保存着對外部函數中變量的引用

頁面加載

加載一個資源的過程

  • 瀏覽器根據DNS服務器得到域名的IP地址
  • 向這個IP的機器發送http請求
  • 服務器收到,處理並返回http請求
  • 瀏覽器得到返回內容

瀏覽器渲染頁面的過程

  • 根據HTML結構生成DOM Tree
  • 根據css生成CSSOM
  • 根據DOM和CSSOM整合形成RenderTree
  • 根據RenderTree開始渲染和展示
  • 遇到script標簽時,會執行並阻塞渲染

前端網頁有那三層構成,分別是什么?作用是什么

  • 結構層HTML,決定網頁的結構
  • 表示層CSS,決定網頁的樣式
  • 行為層JS,決定網頁的行為

什么樣的前端代碼是好的

高復用低耦合,這樣文件小,好維護,而且好擴展

請解釋什么是事件委托

是把原本需要綁定的事件委托給父親,讓父元素擔當事件監聽的職務

簡單的說就是某個時間本來該自己干的,但是自己不干,交給別人來干,就交

<ul id="ul1">
    <li>111</li>
    <li>222</li>
    <li>333</li>
    <li>444</li>
</ul>
實現功能是點擊li,彈出123:

復制代碼
window.onload = function(){
    var oUl = document.getElementById("ul1");
    var aLi = oUl.getElementsByTagName('li');
    for(var i=0;i<aLi.length;i++){
        aLi[i].onclick = function(){
            alert(123);
        }
    }
}

優點可以提高性能

通過HTTP請求響應過程了解HTTP協議

DNS域名解析

發起TCP的3次握手

簡歷TCP連接后發起http請求

服務器端響應http請求,瀏覽器得到html代碼

瀏覽器解析html代碼,並請求html代碼中的資源

瀏覽器對頁面進行渲染呈現給用戶


發起TCP的3次握手

在客戶端和服務器之間建立正常的TCP網絡連接是

客戶端發送SYN給服務器

服務端返回SYN+ACK給客戶端

客戶端確認,返回ACK給服務端

超易錯的CSS優先級關系

 .classB{
        background-color: red;
    }
    .classA{
        background-color: rebeccapurple;
    }
</style>
<!--與樣式定義的前后有關--與標簽的class順序無關-->
<p class="classA classB">1111111</p>

H5與APP混合開發遇到的問題

頁面滾動條問題

web頁面在pc瀏覽時有滾動條,但是在移動端瀏覽器打開時,沒有滾動條

解決方法

給body一個大容器 設置overflow:auto/scroll

其他的兼容性就不說了,看着腦袋疼,解決方案等遇到了再解決吧

說說你對vue聲明周期的理解

分為8個階段,創建前/后,載入前/后,更新前/后,銷毀前/后

  • 創建前/后:在beforeCreate階段,vue實例的掛載元素,el和數據對象data都是undefined,還沒初始化,在created階段,用於發生數據請求,也可以初始化一些數據
  • 載入前后:在beforeMount階段,vue實例的$el和data都初始化了,但還是掛載之前為虛擬的dom節點上,data.message還沒有替換,在mounted階段,vue實例掛載完成,data.message成功渲染
  • 更新前后:當data變化時,出觸發beforeUpdata和updated方法
  • 銷毀前后:在執行destroy方法后,對data 的改變不會在觸發周期函數,說明vue實例已經接觸了事件監聽以及dom的綁定,但是dom結構依然存在

父組件如何將數據傳到子組件

  • 父組件可以通過props傳遞數據到子組件中
  • props是單向綁定的
  • 每次父組件更新是,子組件的所有props都會更新為最新值

子組件如何將數據傳到父組件

  • 子組件可通過vm.$emit將數據傳遞到父組件
  • vm.$emit是觸發當前實例上的事件,附加參數都會傳給監聽器回調

面向對象編程的三個基本特性

封裝.繼承,多態

封裝

  • 也就是把客觀事物封裝成抽象的類
  • 並且類可以把自己的數據和方法只讓可信的類或者對象操作
  • 對不可信的進行信息隱藏

繼承

  • 它可以使用現有類的所有功能,並在無需編寫原來的類的情況下對這個類的情況下對這些功能進行擴展
  • 要實現繼承,可以通過"繼承"和"組合"來實現

多態

  • 后端的,js沒有這個概念

總結

  • 封裝可以隱藏實現細節,使得代碼模塊化,繼承可以擴展已存在的代碼模塊(類)
  • 目的是為了--代碼重用

javascript實現繼承的方式

  • 原型鏈繼承(父類的實例作為子類的原型)

    • 缺點
    • 來自原型對象的引用屬性是所有實例共享的
    • 創建子類實例時,無法向父類構造函數傳參
  • 構造繼承(復制父類的實例屬性給子類)

    • call/apply/bind
    • 缺點:無法實現函數復用,每個子類都有父類實例函數的副本,影響性能
  • 實例繼承

    • 為父類實例添加新特性,作為子類實例返回
  • 拷貝繼承

    • cat.prototype[p]=animal[p]
    • 缺點:效率較低,內存占用高
  • 組合繼承

    • 通過調用父類構造,繼承父類的屬性並保留傳參的有點,然后通過將父類實例作為子類原型,實現函數復用
  • 寄生組合繼承

    • 通過寄生方式,砍掉父類的實例屬性(new),這樣,在調用兩次父類的構造的時候,就不會初始化兩次實例方法/屬性

promise

解決回調問題

最大的好處就是在異步執行的流程中,把執行代碼和處理結果的代碼清晰的分離

promise有三種狀態:等待(pending ). 已完成(fulfilled /f斐o/). 已拒絕(rejected /v jk/)

一個promise的狀態之可能從"等待"轉到"完成"或者"拒絕",不能逆向轉移

promise本質就是一個函數,他可以接受一個函數作為參數,並且會返回promise對象

	promise.then(function(value) {
	// 如果調用了resolve方法,執行此函數
	}, function(value) {
	// 如果調用了reject方法,執行此函數
	});
	promise.then(function(result) {
	    //成功時的處理
	}).catch(function(error) {
	    //錯誤時的處理
})
resolve   /v 肉/    

webpack的loader是干什么的

loader是用來編譯和處理資源的

loader用於對模塊的源代碼進行轉換,loader可以使你在import或"加載"模塊是預處理文件,因此,loader類似於其他構建工具中"任務(task)",並提供了處理前端構建步驟的強大方法

當我們遇到大問題時,首相想到的總是去搜搜看有沒有現成的解決方案,但現實卻難免是沒有解決問題,在這種情況下,我們也可以嘗試去寫一些插件,組件,或者一個通用化的解決方案,來解決自身的問題,同時對自己掌握一些知識也會有幫助,而且嘗試過后可能發現,他也沒這么難

Vue組件的data屬性為什么是函數

每個組件都是Vue的實例,每個組件都應該有自己作用域

函數擁有自己的作用域,可以避免組件共享data屬性

Vue的路由怎么實現的

路由:直接找到與地址匹配的組件,並將其渲染出來,改變瀏覽器地址,但不請求服務器

實現方式:地址中添加#來欺騙瀏覽器,地址的改變是進行頁面內導航

Vue router與location.href的區別

vue router是hash值改變,頁面內跳轉

location.href是頁面跳轉,頁面刷新

Webpack與Gulp的區別

Gulp是一種能夠優化前端代碼的開發流程的工具

webpack是一種模塊化的解決方案

plugins(插件)

plugins並不是直接操作單個文件,他直接對整個構建過程起作用

比如他會將入口引用css文件,都打包獨立的css文件,而不是內嵌在js打包文件中

call 和apply的區別是什么

obj.call(thisObj,arg1,arg2)

obj.apply(thisObj,[arg1,arg2])

兩者作用一致,都是把obj(this)綁定到thisObj,這時候thisObj具備了obj的屬性和方法

區別是call接受的是連續參數,apply接受的是數組參數

typeof和instanceof

typeof用於判斷基本類型,是一元運算符.返回結果是字符串

undefined .boolean .null.string.number.symbol.function.object

instanceof用於判斷對象的類型,是二元運算符.返回結果是布爾值

注意:基本類型與一些特殊類型無法得到真的結果

三角形的實現原理

#aaa{
        width: 0;
        height: 0;
        border:20px solid transparent;
        border-bottom-color:red;
    }

AMD與CMD

AMD:異步模塊定義,所有模塊異步加載,模塊加載不影響后續運行,所有依賴模塊的語言必須寫在回調函數中,提前執行依賴前置主要應用於require.js 一個當多個用

CMD:同步加載 延遲執行 依賴就近,主要應用sea.js推薦每一個模塊職責單一

判斷一個參數是否是一個數組

instanceof方法主要檢測 變量的constructor是否與Array相等,也就是檢測變量的原型鏈是否指向Array構造函數的prototype原型上

arr instanceof Array
arr.constructor ===Array
Array.isArray()
Object.prototype.toString.call(arr)

什么是原型鏈

javascript是面向對象的,每個實例對象都有一個__proto__屬性,該屬性指向它原來對象,這個實例對象的構造函數有一個原型屬性prototype,與實例的__proto__屬性指向同一個對象,當一個對象在查找一個屬性的時,自身沒有就會根據__proto__向它的原型進行查找,如果都沒有,則想他的原型的原型繼續查找,直到查到Object.prototype.__proto__為null,這樣也就形成原型鏈

日常變態題點我

讓自己對原生js又多了一點點小小的認識

false==0

true==1

this是如何工作的

this永遠指向函數運行時所在的對象,而不是函數被創建是所在的對象,匿名函數或者不處於任何對象中的函數指向window

如果call .apply.bind ,指定的this是誰,就是誰

普通的函數調用,函數被誰調用,this就是誰


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM