argin屬性
margin屬性用于設置頁面中元素和元素之間的距離,即定義元素周圍的空間范圍,是頁面排版中一個比較重要的概念。margin屬性的語法格式如下:
margin:auto | length
其中,auto表示根據內容自動調整,length表示浮點數字和單位標識符組成的長度值或百分數,百分數是基于父對象的高度。對于內聯元素來說,左右外延邊距可以是負數值。
margin屬性包含4個子屬性,分別用于控制元素四邊,包括margin-top、margin-left、margin-right、margin-bottom。
提示:
在為margin屬性設置值時,如果提供4個參數值,將按順時針順序作用于上、右、下、左4個邊;如果值提供一個參數值,將作用于4邊;如果2個參數值作用于,第一個作用于上下,第二個作用于左右;3個參數值時作用于,第一個值作用于上,第二個作用于左右,第三個值作用于下。
border屬性
border屬性是內邊距和外邊距的分界線,可以分離不同的HTML元素,border的外邊距是元素的最外圍,在網頁設計中,如果計算元素的款和高,則需要把border屬性計算在內。border屬性的語法格式如下:
border:border-style | border-color | border-width;
border邊框樣式值表
提示
border屬性不僅可以用于設置圖像的邊框,還可以為其他元素設置邊框,如文字和Div等。
padding屬性
在CSS中,可以通過設置padding屬性定位內容于邊框之間的距離,即內邊距。
padding屬性的語法格式如下:
padding:length
padding屬性可以是具體的長度,也可以是相對于上級元素的百分比,但不可以使用負值。
padding屬性包含4個子屬性,分別用于控制元素四邊,包括padding-top、padding-left、padding-right、padding-bottom。分別可以為盒子定義上、右、下、左和個邊值。
Content屬性
在盒子模型中,中間部分content(內部)主要顯示內容,這部分野是整個盒模型的主要部分,其他的如對margin、border、padding所做的操作都對content部分所做的修飾,對于內容部分的操作,也就是對文字,圖像等頁面元素的操作。
、算法題部分
1. 如何獲取瀏覽器URL中查詢字符串中的參數
function getParamsWithUrl(url) { var args = url.split('?'); if (args[0] === url) { return ""; } var arr = args[1].split('&'); var obj = {}; for ( var i = 0; i < arr.length; i++) { var arg = arr[i].split('='); obj[arg[0]] = arg[1]; } return obj; } var href = getParamsWithUrl ('http://www.itlike.com?id=1022&name=撩課&age=1'); console.log(href['name']); // 撩課
2. 寫一個深度克隆方法(es5)?
/** * 深拷貝 * @param {object}fromObj 拷貝的對象 * @param {object}toObj 目標對象 */ function deepCopyObj2NewObj(fromObj, toObj) { for(var key in fromObj){ // 1. 取出鍵值對 var fromValue = fromObj[key]; // 2. 檢查當前的屬性值是什么類型 // 如果是值類型,那么就直接拷貝賦值 if(!isObj(fromValue)){ toObj[key] = fromValue; }else { // 如果是引用類型, // 那么就再調用一次這個方法, // 去內部拷貝這個對象的所有屬性 var tempObj = new fromValue.constructor; console.log(fromValue.constructor); deepCopyObj2NewObj(fromValue, tempObj); toObj[key] = tempObj; } } } /** * 輔助函數, 判斷是否是對象 * @param {object}obj * @returns {boolean} */ function isObj(obj) { return obj instanceof Object; }
3. 對數組[1,2,3,8,2,8]進行去重,es5或者es6方法?
es5四種方式: 方式一: Array.prototype.unique1 = function() { // 1. 定義數組 var temp = []; // 2. 遍歷當前數組 for(var i = 0; i < this.length; i++) { // 3.如果當前數組的第i // 已經保存進了臨時數組, // 那么跳過,否則把當前項 // push到臨時數組里面 if (-1 === temp.indexOf(this[i])) { temp.push(this[i]); } } return temp; }; 方式二: Array.prototype.unique2 = function() { //1. hash為hash表,r為臨時數組 var hash = {}, temp=[]; // 2.遍歷當前數組 for(var i = 0; i < this.length; i++) { // 3. 如果hash表中沒有當前項 if (!hash[this[i]]) { // 4.存入hash表 hash[this[i]] = true; // 5.把當前數組的當前項 // push到臨時數組里面 temp.push(this[i]); } } return temp; }; 方式三: Array.prototype.unique3 = function() { var n = [this[0]]; for(var i = 1; i < this.length; i++){ if (this.indexOf(this[i]) === i) { n.push(this[i]); } } return n; }; 方式四: Array.prototype.unique4 = function() { this.sort(); var re=[this[0]]; for(var i = 1; i < this.length; i++) { if( this[i] !== re[re.length-1]){ re.push(this[i]); } } return re; }; es6實現方式: Array.prototype.unique = Array.prototype.unique || () =>{ return [...new Set(this)]; };
4. 如何判斷一個對象是否為數組?
function isArray(arg) { if (typeof arg === 'object') { return Object.prototype.toString.call(arg) === '[object Array]'; } return false; }
5. 冒泡排序?
思路: 每次比較相鄰的兩個數, 如果后一個比前一個小,換位置; var arr = [2, 0, 1, 9, 8, 7, 3]; function bubbleSort(arr) { for (var i = 0; i < arr.length - 1; i++) { for(var j = 0; j < arr.l i - 1; j++) { if(arr[j + 1] < arr[j]) { var temp; temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } return arr; } console.log(bubbleSort(arr));
6. 快速排序?
思路: 采用二分法,取出中間數, 數組每次和中間數比較, 小的放到左邊,大的放到右邊; var arr = [2, 0, 1, 9, 8, 7, 3]; function quickSort(arr) { if(arr.length == 0) { // 返回空數組 return []; } var cIndex = Math.floor(arr.length / 2); var c = arr.splice(cIndex, 1); var l = []; var r = []; for (var i = 0; i < arr.length; i++) { if(arr[i] < c) { l.push(arr[i]); } else { r.push(arr[i]); } } return quickSort(l).concat(c, quickSort(r)); } console.log(quickSort(arr));
7. 正則表達式驗證郵箱格式?
var reg = /^(\w)+(\.\w+)*@(\w)+((\.\w{2,3}){1,3})$/; var email = "yjh@itlike.com"; console.log(reg.test(email)); // true
8. 正則表達式清除字符串前后的空格?
function trim(str) { if (str && typeof str === "string") { // 去除前后空白符 return str.replace(/(^\s*)|(\s*)$/g,""); } }
二、JS系列部分
1. var的變量提升的底層原理是什么?
JS引擎的工作方式是: 1) 先解析代碼,獲取所有被聲明的變量; 2) 然后在運行。也就是說分為預處理和執行兩個階段。 補充: 變量提升:所有變量的聲明語句都會被提升到代碼頭部。 但是變量提升只對var命令聲明的變量有效,如果一個變量不是 用var命令聲明的,就不會發生變量提升。 js里的function也可看做變量,也存在變量提升情況。
2. JS如何計算瀏覽器的渲染時間?
瀏覽器的渲染過程主要包括以下幾步: 1) 解析HTML生成DOM樹。 2) 解析CSS生成CSSOM規則樹。 3) 將DOM樹與CSSOM規則樹合并在一起生成渲染樹。 4) 遍歷渲染樹開始布局,計算每個節點的位置大小信息。 5) 將渲染樹每個節點繪制到屏幕。 優化考慮: CSS 優先:引入順序上,CSS 資源先于 JavaScript 資源。 JS置后:通常把JS代碼放到頁面底部,且JavaScript 應盡量少影響 DOM 的構建。
3. JS的回收機制?
垃圾回收機制就是間歇的不定期的尋找到不再使用的變量, 并釋放掉它們所指向的內存; 主要為了以防內存泄漏, (內存泄漏: 當已經不需要某塊內存時這塊內存還存在著), JS有兩種變量: 全局變量和在函數中產生的局部變量。 局部變量的生命周期在函數執行過后就結束了, 此時便可將它引用的內存釋放(即垃圾回收); 但全局變量生命周期會持續到瀏覽器關閉頁面。 JS執行環境中的垃圾回收器有兩種方式: 標記清除(mark and sweep)、 引用計數(reference counting)。 標記清除: 垃圾收集器給內存中的所有變量都加上標記, 然后去掉環境中的變量以及被環境中的變量引用的變量的標記。 在此之后再被加上的標記的變量即為需要回收的變量, 因為環境中的變量已經無法訪問到這些變量。 引用計數(reference counting): 這種方式常常會引起內存泄漏, 低版本的IE使用這種方式。機制就是跟蹤一個值的引用次數, 當聲明一個變量并將一個引用類型賦值給該變量時該值引用次數加1, 當這個變量指向其他一個時該值的引用次數便減一。 當該值引用次數為0時就會被回收。
4. 寫一下節點增刪改?
// 注意:動態創建元素不會直接顯示在頁面當中, // 前面必須是document,不能是其他 1)document.createElement(標簽名); // 在指定父級子節點最后一個后面追加子元素 2)父級.appendChild(要追加的元素) ; // 在父級的指定子元素前面插入一個新元素 (注意:先判斷如果第二個參數的節點是否存在) 3)父級.insertBefore(新的元素,指定的已有子元素); // 深克隆(負值標簽、標簽屬性、標簽里面內容); // 淺克隆(負值標簽、標簽屬性不復制標簽里面內容) 4)元素.cloneNode(true) 或者元素.cloneNode(false); 5)父級.removeChild(已有子元素); 6)父級.replaceChild(新的元素節點,原有元素節點);
5. 如何獲取元素的父節點和兄弟節點,寫一下?
獲取父節點: // 1. parentNode獲取父節點 // 獲取的是當前元素的直接父元素。 var p = document.getElementById("test").parentNode; // 2. parentElement獲取父節點 // parentElement和parentNode一樣, 只是parentElement是ie的標準。 var p1 = document.getElementById("test").parentElement; // 3. offsetParent獲取所有父節點 var p2 = document.getElementById("test").offsetParent; 獲取兄弟節點: // 1. 通過獲取父親節點再獲取子節點來獲取兄弟節點 var brother1 = document.getElementById("test").parentNode.children[1]; // 2. 獲取上一個兄弟節點 // 在獲取前一個兄弟節點的時候可以使用previousSibling // 和previousElementSibling。 // 他們的區別是previousSibling會匹配字符, // 包括換行和空格,而不是節點。 // previousElementSibling則直接匹配節點。 var brother2 = document.getElementById("test").previousElementSibling; var brother3 = document.getElementById("test").previousSibling; // 3. 獲取下一個兄弟節點 var brother4 = document.getElementById("test").nextElementSibling; var brother5 = document.getElementById("test").nextSibling;
6. 給你一個亂序數組,你怎么排序?
撩課小編: sort, 冒泡, 選擇, 二分法....
7. 原生JS都有哪些方式可以實現兩個頁面間的通信?
1) 通過url地址欄傳遞參數; 例如:點擊列表頁中的每一條數據, 我們跳轉到同一個詳細頁面, 但是根據點擊的不一樣可以看到 不同的內容,這樣的話我們就可以 在URL中傳遞不同的值來區分了; 2) 通過本地存儲 cookie、localeStorage、 sessionStroage...,例如:京東的登錄, 我們在登錄頁登錄完成后, 把用戶信息存儲到本地, 然后在其它頁面中如果需要使用的話, 我們直接從本地的存儲數據中拿 出來用即可; 3) 使用iframe在A頁面中嵌入B頁面, 這樣的話,在A中可以通過一些屬性 和方法實現和B頁面的通信; 4) 利用postMessage實現頁面間通信, 父窗口往子窗口傳遞信息, 子窗口往父窗口傳遞信息。
8. 原生JS動態向一個div中插入1000個div標簽,如何實現?
此題主要考性能! 1) 可以用JS中的createElement創建div, 每當創建一個就把它添加到div中, 但會造成引發回流的次數太多; 2) 使用字符串拼接的方式, 把1000個div都拼接完成后, 統一的添加到頁面中, 但會對div原有的元素標簽產生影響: 原來標簽綁定的事件都消失了 3) 綜合1和2可以使用文檔碎片方式來處理。 追問:如果是創建1000萬個呢? 可采用的方案: 數據分批異步加載 1) 首先把前兩屏幕的數據量 (例如:300條)先獲取到, 然后使用字符串拼接或者文檔碎片 的方式綁定到頁面中; 2) 當瀏覽器滾動到指定的區域的 時候在加載300條...以此類推。
9. 程序出現bug了,你是如何調試的?
1) 在控制臺加斷點, F10->逐過程 F11->逐語句; 2) 在代碼重點的位置加入console.log輸出對應的值來進行調試; 3) debugger調試; 4) 代碼分割還原調試; 5) 異常捕獲機制, 記錄運行日志; 6) 單元測試。
10. 開發中是如何進行性能優化的?
現在框架(vue, react,...)、構建工具(webpack, ...) 已經給我們解決掉大部分的性能優化問題, 面試時, 可以就你了解的框架來深入剖析, 但此題應該是考原生JS的范疇, 參考答案如下: 1) 雅虎35條性能優化黃金定律; 2) JS代碼優化: a. 項目中的JS/CSS文件最好一個頁面只用一個, 需要把JS/CSS進行合并壓縮, 并且減少頁面中的垃圾冗余代碼。 項目的資源文件在服務器上最好 做一下GZIP壓縮。 b. 解除文件緩存; 我們修改代碼并上傳, 如果之前頁面訪問過該網站, 很有可能不能立即見效; 我們在引入CSS/JS文件的時候, 在文件名的后面加上版本號(加時間戳), 比如: <script src='itlike.com.js?_=202001...'></script>; 當我們上傳新的文件后 把時間戳改一下就可以清除緩存了。 c. 移動端盡量少用圖片: icon能用svg畫的不用圖片; 靜態資源圖:做布局的時候就能確定下來的圖片, 比如: 1)css sprite圖片合并(針對于小圖片) 2)做圖片延遲加載 (針對于大圖片 頭部的長條圖片、背景大圖...), 開始給一張默認的小的圖片 (最好維持在10kb以內) 3)base64 (存在問題: 頁面的代碼太臃腫了,以后維護不好操作); 如果項目中由于圖片太大實在解決不了, 改成base64就解決了 d. 動態數據圖: 通過ajax從后臺讀取回來的圖片 , 圖片懶加載; e. 音視頻文件的優化: 加載頁面的時候,盡量不要加載音視頻文件, 當頁面中的其他資源加載完成后, 再開始加載音視頻文件; 目前移動端經常給音視頻做的優化是: 走直播流文件(音頻后綴名是m3u8格式); f. 減少頁面資源請求的次數: 如果當前只是一個宣傳頁, 或者是一個簡單的頁面, 使用的css和js可以采用內嵌式開發; g. ajax數據請求分批請求, 例如:一次要請求10000條數據的話, 我們每一次只請求100條,第一屏幕肯定能看全了, 當頁面滾動到對應的其它屏幕的時候, 在加載下一個100條... h. 做數據的二次緩存, 能用CSS3做動畫的絕對不用JS, 能使用transform盡量使用, 能用animation的進行不用transition... 盡量減少同步操作,多用異步操作; 能使用原生JS自己編寫的, 絕對不用插件或者框架;
在這里插入圖片描述
11. 請描述下JS中事件冒泡機制?冒泡型事件:事件按照從最特定的 事件目標到最不特定的事件目標 (document對象)的順序觸發。 捕獲型事件:事件從最不精確的對 象(document 對象)開始觸發,然后 到最精確。(也可以在窗口級別捕獲 事件,不過必須由開發人員特別指定)。 支持W3C標準的瀏覽器在添加事件時 用addEventListener(event,fn,useCapture)方法, 基中第3個參數useCapture是一個Boolean值, 用來設置事件是在事件捕獲時執行, 還是事件冒泡時執行。 而不兼容W3C的瀏覽器(IE)用attachEvent()方法, 此方法沒有相關設置, 不過IE的事件模型默認是在事件冒泡時執行的, 也就是在useCapture等于false的時候執行, 所以把在處理事件時把useCapture 設置為false是比較安全, 也實現兼容瀏覽器的效果。 如下圖所示:
在這里插入圖片描述
12. 為什么利用多個域名來提供網站資源會更有效?1.CDN緩存更方便 2.突破瀏覽器并發限制 (一般每個域名建立的鏈接不超過6個) 3.Cookieless,節省帶寬, 尤其是上行帶寬一般比下行要慢; 4.對于UGC的內容和主站隔離, 防止不必要的安全問題 (上傳js竊取主站cookie之類的)。 正是這個原因要求用戶內容的域名 必須不是自己主站的子域名, 而是一個完全獨立的第三方域名。 5.數據做了劃分, 甚至切到了不同的物理集群, 通過子域名來分流比較省事。 補充: 關于Cookie的問題, 帶寬是次要的,安全隔離才是主要的。 關于多域名,也不是越多越好, 雖然服務器端可以做泛解釋, 瀏覽器做dns解釋也是耗時間的, 而且太多域名,如果要走https的話, 還有要多買證書和部署的問題。
13. 請說出三種減少頁面加載時間的方法?
1.優化圖片; 精靈圖片, 字體圖標 SVG, GIF, WEBP (可用在一些對顏色要求不高的地方) 2. 優化CSS (壓縮合并css, 如margin-top,margin-left...) 3. 網址后加斜杠 (如www.itlike.com/目錄, 會判斷這個“目錄是什么文件類型, 或者是目錄。) 4. 標簽標明高度和寬度 (如果瀏覽器沒有找到這兩個參數, 它需要一邊下載圖片一邊計算大小, 如果圖片很多, 瀏覽器需要不斷地調整頁面。 這不但影響速度,也影響瀏覽體驗。 當瀏覽器知道了高度和寬度參數后, 即使圖片暫時無法顯示, 頁面上也會騰出圖片的空位, 然后繼續加載后面的內容。 從而加載時間快了, 瀏覽體驗也更好了。) 5.減少http請求 (合并文件,合并圖片)。
14. cookie 和session 的區別?
1. cookie數據存放在客戶的瀏覽器上, session數據放在服務器上。 2. cookie不是很安全, 別人可以分析存放在本地的COOKIE, 并進行COOKIE欺騙, 考慮到安全應當使用session。 3. session會在一定時間內保存在服務器上。 當訪問增多,會比較占用你服務器的性能 考慮到減輕服務器性能方面, 應當使用COOKIE。 4. 單個cookie保存的數據不能超過4K, 很多瀏覽器都限制一個站點最多保存20個cookie。 5. 開發建議:將登錄,用戶等重要信息存放為session, 其他信息如果需要保留,可以放在cookie中。 PS: 額外閱讀 應用場景 經常登錄一個網站, 今天輸入用戶名密碼登錄了, 第二天再打開很多情況下就直接打開了 。這個時候用到的一個機制就是cookie。 session的一個場景是購物車, 添加了商品之后客戶端處 可以知道添加了哪些商品, 而服務器端如何判別呢, 所以也需要存儲一些信息, 這里就用到了session。 Cookie Cookie是訪問某些網站以后 在本地存儲的一些網站相關的信息, 下次再訪問的時候減少一些步驟。 另外一個更準確的說法是: Cookies是服務器在本地機器上 存儲的小段文本并隨每一個請求 發送至同一個服務器, 是一種在客戶端保持狀態的方案。 Cookie的主要內容包括: 名字,值,過期時間,路徑和域。 Session Session是存在服務器的 一種用來存放用戶數據的類 HashTable結構。 當瀏覽器 第一次發送請求時, 服務器自動生成了一個HashTable 和一個Session ID用來唯一標識這個HashTable, 并將其通過響應發送到瀏覽器。 當瀏覽器第二次發送請求, 會將前一次服務器響應中的Session ID 放在請求中一并發送到服務器上, 服務器從請求中提取出Session ID, 并和保存的所有Session ID進行對比, 找到這個用戶對應的HashTable。 一般這個值會有一個時間限制, 超時后毀掉這個值,默認是20分鐘。 Session的實現方式和Cookie有一定關系。 試想一下,建立一個連接就生成一個session id, 那么打開幾個頁面就好幾個了, 這顯然不是我們想要的, 那么該怎么區分呢? 這里就用到了Cookie, 我們可以把session id存在Cookie中, 然后每次訪問的時候將 Session id帶過去就可以識別了 15. 如何理解閉包? 為什么要使用閉包: 因為JS中變量的作用域分類: 全局變量和局部變量。 函數內部可以讀取函數外部的全局變量; 在函數外部無法讀取函數內的局部變量。 為了讓函數執行完成后,內部的函數、變量還 能被調用,可以采用閉包延長 局部變量/函數的生命周期。 定義和用法: 當一個函數的返回值是 另外一個函數,而返回的那個函數 如果調用了其父函數內部的其它變量, 如果返回的這個函數在外部被執行, 就產生了閉包。 表現形式: 使函數外部能夠調用 函數內部定義的變量。 使用場景: 排他、函數節流、網絡... 使用閉包的注意點: 濫用閉包,會造成內存泄漏; 由于閉包會使得函數中的變量 都被保存在內存中,內存消耗很大, 所以不能濫用閉包, 否則會造成網頁的性能問題, 在IE中可能導致內存泄露。 解決方法是,在退出函數之前, 將不使用的局部變量指向null。
16.JS有哪些手段可以實現繼承?
1. 原型鏈繼承 將父類的實例作為子類的原型; 2. 借助構造函數繼承 使用父類的構造函數來增強子類實例, 等于是復制父類的實例屬性給子類; (沒用到原型) 3. 寄生組合繼承(完美) 通過寄生方式, 砍掉父類的實例屬性, 這樣,在調用兩次父類的構造的時候, 就不會初始化兩次實例方法/屬性, 避免的組合繼承的缺點 4. 組合繼承 通過調用父類構造, 繼承父類的屬性并保留傳參的優點, 然后通過將父類實例作為子類原型, 實現函數復用 5. 拷貝繼承 支持多繼承,無法獲取父類 不可枚舉的方法 6. 實例繼承 為父類實例添加新特性, 作為子類實例返回
17. 用純JS實現,點擊一個列表時,輸出對應的索引?
方式一: for(let i = 0, len = lis.length; i < len; i++){ lis[i].addEventListener('click', function () { console.log(i); }, false); } 方式二: for(var i = 0, len = lis.length; i < len; i++) { (function (i) { lis[i].addEventListener ('click', function () { console.log(i); }, false); })(i) } 方式三: let ul = document.querySelector('ul'); let lis = document.querySelectorAll('ul li'); ul.addEventListener('click', function (e) { let target = e.target; if(target.nodeName.toLowerCase() === 'li') { console.log([].indexOf.call(lis, target)); } }, false);
18. 以下代碼有內存泄漏嗎?
var user = { name: '撩課', age: 12, gender: '女' }; var box = document.getElementById('box'); box.onclick = function() { box.innerHTML = user.name; }; // ...其他操作 user = null; // 釋放對象 答:存在內存泄漏, 這是js中垃圾回收的引用計數造成的。 完全去除內存泄漏是不現實的,但是, 如果采用下面的方法可以減少內存泄漏: var user = { name: '撩課', age: 12, gender: '女' }; var box = document.getElementById('box'); (function (name) { box.onclick = function() { box.innerHTML = name; }; })(user.name); // ...其他操作 user = null; // 釋放對象
19. es6中let,const,var的區別是什么?
var :聲明全局變量; let :聲明塊級變量,即局部變量, 定義后可以修改; const :用于聲明常量,就是定義后不能再修改值或者引用值的常量,也具有塊級作用域4
20. 說說對es6中=>的理解?
箭頭函數相當于匿名函數, 并且簡化了函數定義, 箭頭左邊是參數, 右邊是返回值。 箭頭函數看上去 是匿名函數的一種簡寫, 但實際上,箭頭函數和 匿名函數有個明顯的區別: 箭頭函數內部的this是詞法作用域, 由上下文確定。
21. 點擊按鈕發出ajax請求,如何防止用戶在此請求方式返回之前再次點擊?
// 點擊提交按鈕的時候, // 把這個提交這個處理函數給解綁掉, // 請求完成的時候在綁定回來 function clickHandler(){ $(this).unbind('click', clickHandler); $.ajax({ url : 'url', dataType : 'json', type : 'post', success : function (data) { if (data.success) { //提交成功做跳轉處理 } else { //處理失敗,重新綁定點擊事件 $(self).click(clickHandler); } } }); } $('#itlike').click(clickHandler); // 可以點擊后讓按鈕不可用, // 如果提交失敗可以再次設置為可用 // 1.讓按鈕不可用 $("#itlike").attr("disabled","disabled"); $.ajax({ url : 'url', dataType : 'json', type : 'post', success : function (data) { if (data.success) { // 提交成功做跳轉處理 } else { // 處理失敗,重新綁定點擊事件 // 2. 讓按鈕可用 $("#itlike").removeAttr("disabled"); } } });
22. 請說明ECMAScript, JavaScript, Jscript之間的關系?
ECMAScript提供腳本語言必須遵守的規則、 細節和準則,是腳本語言的規范。 比如:ES5,ES6就是具體的一js版本。 JavaScript是ECMAScript的一個分支版本, JavaScript 實現了多數 ECMA-262 中 描述的 ECMAScript 規范,但存在少數差異。 JScript是微軟公司對ECMA-262語言規范的 一種實現,除了少數例外(這是為了保持向后兼容 ), 微軟公司宣稱JScript完全實現了ECMA標準. 關系: JavaScript和JScript都是ECMAScript的版本分支, 二者在語法上沒有多大的區別; 只不過一個是NetScape公司的, 一個是微軟的; IE系列默認是JScript, 其它的則反之用JavaScript。
23. 頁面加載過程中可能觸發哪些事件? 它們的順序是?
頁面加載時,大致可以分為以下幾個步驟: 1) 開始解析HTML文檔結構; 2) 加載外部樣式表及JavaScript腳本; 3) 解析執行JavaScript腳本; 4) DOM樹渲染完成; 5) 加載未完成的外部資源(如 圖片); 6) 頁面加載成功 執行順序: 1) document readystatechange事件 2) document DOMContentLoaded事件 3) window load事件
24. 函數中在聲明變量a前使用a會產生錯誤嗎? 為什么?
不會, JS中能夠進行變量作用域提升, 把所有變量、函數的聲明提升到當前 作用域的最前面, 但不進行賦值操作; 所以可能造成獲取的值是undefined。
25. 什么是hash, 以及hashchange事件?
先了解下什么是hash:hash即URL中"#"字符后面的部分: a) 使用瀏覽器訪問網頁時, 如果網頁URL中帶有hash, 頁面就會定位到id(或name) 與hash值一樣的元素的位置; b) hash還有另一個特點, 它的改變不會導致頁面重新加載; c) hash值瀏覽器是不會隨請求發送到服務器端的; d) 通過window.location.hash屬性獲取和設置hash值。 window.location.hash值的變化會直接 反應到瀏覽器地址欄(#后面的部分會發生變化), 同時,瀏覽器地址欄hash值的變化也會觸發 window.location.hash值的變化, 從而觸發onhashchange事件。 再來了解下什么是hashchange事件: a) 當URL的片段標識符更改時, 將觸發hashchange事件 (跟在#符號后面的URL部分,包括#符號) b) hashchange事件觸發時, 事件對象會有hash改變前的URL (oldURL)和hash改變后的URL (newURL)兩個屬性。
26. 什么是CDN, CDN對于網站有什么意義, 它有什么樣的缺點?
CDN又稱為內容分發網絡; 本意在于 盡可能避開互聯網上有可能影響數據 傳輸速度和穩定性的瓶頸和環節, 使內容傳輸的更快、更穩定。 主要目的: 解決因分布、帶寬、服務器性能帶來的訪問延遲問題, 適用于站點加速、點播、直播等場景。 使用戶可就近取得所需內容, 解決 Internet網絡擁擠的狀況, 提高用戶訪問網站的響應速度和成功率。 缺點: a) 實施復雜 , 投資大; b) 目前大部分的CDN還只是對靜態內容加速, 對動態加速效果不好; 而雙線對動態加速的效果跟靜態是一樣的。
27. 說說你對作用域鏈的理解?
作用域鏈的作用是保證執行環境里 有權訪問的變量和函數是有序的, 作用域鏈的變量只能向上訪問, 變量訪問到window對象即被終止, 作用域鏈向下訪問變量是不被允許的; 作用域就是變量與函數的可訪問范圍, 即作用域控制著變量與函數的可見性 和生命周期。
28. 請說說JavaScript原型,原型鏈 ?
原型: 當我們訪問一個對象的屬性時, 每個對象都會在其內部初始化一個屬性, 就是prototype(原型); 原型鏈: 如果這個對象內部不存在這個屬性, 那么他就會去prototype里找這個屬性, 這個prototype又會有自己的prototype, 于是就這樣一直找下去, 也就是我們平時所說的原型鏈; 兩者關系: instance.constructor.prototype = instance.__proto__
29. 請解釋什么是事件代理?
事件代理(Event Delegation), 又稱之為事件委托。 是 JavaScript 中常用綁定事件 的常用技巧。 “事件代理”即是把原本需要綁定 的事件委托給父元素,讓父元素 擔當事件監聽的角色。 事件代理的原理是DOM元素的事件冒泡。 使用事件代理的好處是可以提高性能, 可以大量節省內存占用,減少事件注冊, 比如在ul上代理所有li的click事件; 此外, 還可以實現動態新增子對象時無需 再次對其綁定事件。
30. new操作符具體完成了哪幾個操作?
1) 創建一個空對象, 定義this 變量引用該對象,同時還繼承了該函數的原型; 2) 屬性和方法被加入到 this 引用的對象中; 3) 新創建的對象由 this 所引用, 并且最后隱式的返回 this 31. 說幾條寫JavaScript的基本規范? 1) 不要在同一行聲明多個變量; 2) 請使用===/!==來比較true/false或者數值; 3) 使用對象字面量替代new Object這種形式; 4) 減少使用全局函數, 全局變量; 5) switch語句必須帶有default分支; 6) if語句必須使用大括號; 7) for-in循環中的變量; 應該使用var關鍵字明確限定作用域; 從而避免作用域全局污染。
32. 如何解決跨域問題?
1) jsonp 2) iframe 3) window.name 4) window.postMessage 5) 服務器上設置代理頁面
33. XML和JSON的區別?
1) 數據體積方面JSON相對于XML來講, 數據的體積小,傳遞的速度更快些。 2) 數據交互方面JSON與JavaScript的交互更加方便, 更容易解析處理,更好的數據交互。 3) 數據描述方面;JSON對數據的描述性比XML較差。 4) 傳輸速度方面:JSON的速度要遠遠快于XML。
34. 在Javascript中什么是偽數組?如何將偽數組轉化為標準數組?
偽數組(類數組): 無法直接調用數組方法, length屬性有什么特殊的行為, 但仍可以對真正數組遍歷方法來遍歷它們。 典型的是函數的argument參數, 還有像調getElementsByTagName,document.childNodes之類的, 它們都返回NodeList對象, 這些都屬于偽數組。 可以使用Array.prototype.slice.call(fArray)將數組 轉化為真正的Array對象。
35. 一次完整的HTTP事務是怎樣的一個過程?
基本流程: a. 域名解析; b. 發起TCP的3次握手; c. 建立TCP連接后發起http請求; d. 服務器端響應http請求,瀏覽器得到html代碼; e. 瀏覽器解析html代碼,并請求html代碼中的資源; f. 瀏覽器對頁面進行渲染呈現給用戶
36. 開發中有哪些常見的Web攻擊技術?
a) XSS (Cross-Site Scripting,跨站腳本攻擊) 指通過存在安全漏洞的Web網站注冊用戶的瀏覽器 內運行非法的HTML標簽或者JavaScript進行的一種攻擊。 b)SQL注入 c) CSRF (Cross-Site Request Forgeries,跨站點請求偽造) 指攻擊者通過設置好的陷阱,強制對已完成的認證用戶進行 非預期的個人信息或設定信息等某些狀態更新。
三、H5+C3部分
1. 垂直水平居中的方式?
/** 方式一: 定位 父元素設置為:position: relative; 子元素設置為:position: absolute; 距上50%,據左50%,然后減去元素自身寬度的距離就可以實現 */ width: 100px; height: 100px; position: absolute; left: 50%; top: 50%; margin: -50px 0 0 -50px; /** 方式二: flex布局 */ display: flex; //flex布局 justify-content: center; // 使子項目水平居中 align-items: center; // 使子項目垂直居中 /** 方式三: table-cell (不推薦) */ display: table-cell; vertical-align: middle;//使子元素垂直居中 text-align: center;//使子元素水平居中
2. 實現一個三欄布局,中間版塊自適應方法有哪些?
// 方式一: 浮動和定位 <div class="content"> <div class="left">left</div> <div class="right">right</div> <div class="center">center</div> </div> .left{ float: left; width: 100px; height: 200px; } .right{ float: right; padding: 0; width: 100px; height: 200px; } .center{ margin: 0 100px 0 200px; } 方式二: 將父容器的position設置為relative,兩個邊欄的position設置成absolute。
3. margin坍塌?
當兩個盒子在垂直方向上設置margin值時,會出現塌陷現象。 解決方案主要包括: 1. 給父盒子添加border; 2. 給父盒子添加padding-top; 3. 給父盒子添加overflow:hidden; 4. 父盒子position:fixed; 5. 父盒子display:table; 6. 給子元素的前面添加一個兄弟元素 屬性為content:"";overflow:hidden;
4. 說說BFC原理?
BFC就是頁面上的一個隔離的獨立容器, 容器里面的子元素不會影響到外面的元素。 因為BFC內部的元素和外部的元素絕對不會互相影響, 因此,當BFC外部存在浮動時, 它不會影響BFC內部Box的布局, BFC會通過變窄,而不與浮動有重疊。 同樣的,當BFC內部有浮動時, 為了不影響外部元素的布局, BFC計算高度時會包括浮動的高度。 避免margin重疊也是這樣的一個道理。
5. 為什么要清除浮動?舉個實際場景?
父元素的高度是由子元素撐開的, 且子元素設置了浮動, 父元素沒有設置浮動, 子元素脫離了標準的文檔流, 那么父元素的高度會將其忽略, 如果不清除浮動, 父元素會出現高度不夠, 那樣如果設置border或者background都得不到正確的解析。 方式: .clearfix::after, .clearfix::before{ content:""; display:table; clear:both; }
6. 你能描述一下漸進增強和優雅降級之間的不同嗎?
定義: 優雅降級(graceful degradation): 一開始就構建站點的完整功能, 然后針對瀏覽器測試和修復 漸進增強(progressive enhancement): 一開始只構建站點的最少特性, 然后不斷針對各瀏覽器追加功能。 優雅降級和漸進增強都關注于同一網站 在不同設備里不同瀏覽器下的表現程度。 區別: “優雅降級”觀點認為應該針對那些最高級、 最完善的瀏覽器來設計網站。 而將那些被認為“過時”或有功能缺失的瀏覽器下 的測試工作安排在開發周期的最后階段,并把測試 對象限定為主流瀏覽器(如 IE、Mozilla 等)的 前一個版本。 “漸進增強”觀點則認為應關注于內容本身。 總結: "優雅降級"就是首先完整地實現整個網站, 包括其中的功能和效果. 然后再為那些無 法支持所有功能的瀏覽器增加候選方案, 使之在舊式瀏覽器上以某種形式降級體驗 卻不至于完全失效。 "漸進增強"則是從瀏覽器支持的基本功能開始, 首先為所有設備準備好清晰且語義化的html及 完整內容, 然后再以無侵入的方法向頁面增加無 害于基礎瀏覽器的額外樣式和功能。 當瀏覽器升級時, 它們會自動呈現并發揮作用。
7. 請說說瀏覽器內核的組成?
瀏覽器的結構: 1)用戶界面(UI) 包括菜單欄、工具欄、地址欄、后退/前進按鈕、書簽目錄等, 也就是能看到的除了顯示頁面的主窗口之外的部分; 2)瀏覽器引擎(Rendering engine) 也被稱為瀏覽器內核、渲染引擎,主要負責取得頁面內容、 整理信息(應用CSS)、計算頁面的顯示方式,然后會輸出到 顯示器或者打印機; 3)JS解釋器 也可以稱為JS內核,主要負責處理javascript腳本程序, 一般都會附帶在瀏覽器之中,例如chrome的V8引擎; 4)網絡部分 主要用于網絡調用,例如:HTTP請求, 其接口與平臺無關,并為所有的平臺提供底層實現; 5)UI后端 用于繪制基本的窗口部件,比如組合框和窗口等。 6)數據存儲 保存類似于cookie、storage等數據部分, HTML5新增了web database技術,一種完整的輕量級客 戶端存儲技術。 主要瀏覽器: IE、Firefox、Safari、Chrome、Opera。 它們的瀏覽器內核(渲染引擎): IE--Trident FF(Mozilla)--Gecko Safari--Webkit Chrome--Blink(WebKit的分支) Opera--原為Presto,現為Blink
8. 為什么利用多個域名來請求網絡資源會更有效?
動靜分離需求,使用不同的服務器處理請求。 處理動態內容的只處理動態內容,不處理別的, 提高效率。 突破瀏覽器并發限制, 同一時間針對同一域名 下的請求有一定數量限制。超過限制數目的請 求會被阻止。不同瀏覽器這個限制的數目不一樣。 Cookieless, 節省帶寬,尤其是上行帶寬一般比下 行要慢。用戶的每次訪問,都會帶上自己的cookie ,久而久之耗費的帶寬還是挺大的。 假如weibo 的圖片放在主站域名下,那么用戶 每次訪問圖片時,request header 里就會帶有 自己的cookie ,header 里的cookie 還不能壓縮, 而圖片是不需要知道用戶的cookie 的,所以這部分帶 寬就白白浪費了。 避免不必要的安全問題(比如: 上傳js竊取主站cookie之類的) 節約主域名的連接數,從而提高客戶端網絡帶寬的利用率, 優化頁面響應。
9. 說說前端開發中, 如何進行性能優化?
1) 減少http請求次數:css spirit,data uri; 2) JS,CSS源碼壓縮; 3) 前端模板 JS+數據,減少由于HTML標簽導致 的帶寬浪費,前端用變量保存AJAX請求結果,每 次操作本地變量,不用請求,減少請求次數; 4) 用innerHTML代替DOM操作,減少DOM操作次數; 5) 用setTimeout來避免頁面失去響應; 6) 用hash-table來優化查找; 7) 當需要設置的樣式很多時設置className而不 是直接操作style; 8) 少用全局變量; 9) 緩存DOM節點查找的結果; 10) 避免使用CSS Expression; 11) 圖片預載; 12) 避免在頁面的主體布局中使用table, table要等其中的內容完全下載之后才會顯示出來, 顯示比div+css布局慢; 13) 控制網頁在網絡傳輸過程中的數據量; 比如: 啟用GZIP壓縮或者保持良好的編程習慣, 避免重復的CSS,JavaScript代碼, 多余的HTML標簽和屬性。
10. 從前端角度出發, 談談做好網站seo需要考慮什么?
1) 語義化html標簽; 2) 合理的title, description, keywords; 3) 重要的html代碼放前面; 4) 少用iframe, 搜索引擎不會抓取iframe中的內容 5) 圖片加上alt
11. HTTP狀態碼及其含義?
1XX:信息狀態碼 100 Continue 繼續,一般在發送post請求時, 已發送了http header之后服務端將返回此信息, 表示確認,之后發送具體參數信息; 2XX:成功狀態碼 200 OK 正常返回信息 201 Created 請求成功并且服務器創建了新的資源 202 Accepted 服務器已接受請求,但尚未處理 3XX:重定向 301 Moved Permanently 請求的網頁已永久移動到新位置。 302 Found 臨時性重定向。 303 See Other 臨時性重定向,且總是使用 GET 請求新的 URI。 304 Not Modified 自從上次請求后,請求的網頁未修改過。 4XX:客戶端錯誤 400 Bad Request 服務器無法理解請求的格式, 客戶端不應當嘗試再次使用相同的內容發起請求。 401 Unauthorized 請求未授權。 403 Forbidden 禁止訪問。 404 Not Found 找不到如何與 URI 相匹配的資源。 5XX: 服務器錯誤 500 Internal Server Error 最常見的服務器端錯誤。 503 Service Unavailable 服務器端暫時無法處理請求 (可能是過載或維護)。
12. html5有哪些新特性、移除了那些元素?
HTML5 現在已經不是 SGML 的子集, 主要是關于圖像,位置,存儲,多任務等功能的增加: 1) 繪畫標簽canvas; 2) 用于媒介回放的 video 和 audio 元素; 3) 本地離線存儲 localStorage 長期存儲數據, 瀏覽器關閉后數據不丟失; 4) sessionStorage的數據在瀏覽器關閉后自動刪除; 5) 語意化更好的內容元素, 比如article、footer、header、nav、section; 6) 表單控件,calendar、date、time、email、url、search; 7) webworker, websocket, Geolocation; 移除的元素: 1) 純表現的元素:basefont,big,center,font, s,strike,tt,... 2) 對可用性產生負面影響的元素:frame,frameset,noframes
13. display: none;與visibility: hidden;的區別?
相同點:它們都能讓元素不可見 不同點: display:none;會讓元素完全從渲染樹中消失, 渲染的時候不占據任何空間; visibility: hidden;不會讓元素從渲染樹消失, 渲染師元素繼續占據空間,只是內容不可見; display: none;是非繼承屬性, 子孫節點消失由于元素從渲染樹消失造成, 通過修改子孫節點屬性無法顯示; visibility: hidden;是繼承屬性, 子孫節點消失由于繼承了hidden, 通過設置visibility: visible;可以讓子孫節點顯示; 修改常規流中元素的display通常會造成文檔重排。 修改visibility屬性只會造成本元素的重繪。 讀屏器不會讀取display: none;元素內容; 會讀取visibility: hidden;元素內容
14. px和em的區別?
px和em都是長度單位; 區別是: px的值是固定的,指定是多少就是多少, 計算比較容易。 em得值不是固定的,并且em會繼承父級元素的字體大小。 瀏覽器的默認字體高都是16px; 所以未經調整的瀏覽器都符合: 1em=16px; 那么12px=0.75em, 10px=0.625em
15. CSS 去掉inline-block元素間隙的幾種方法?
天在講塊級元素與行內元素區別的時候,我們有提到margin與padding這兩個值,這其實已經涉及到以后會和大家一起討論的css相關知識了。margin中文是‘邊’的意思,在css里面做為‘外邊距’的意思。padding中文有‘襯墊,填塞料’的意思,在css里面做為‘內邊距’的意思。
外邊距,內邊距?要了解這兩個,我們先說一下什么叫css,css英文全稱是cascading style sheets ,中文意思是層疊樣式表,它實際上的作用是用于控制html元素在頁面上的大小形狀,位置,顏色,布局等。通俗一點理解就是相當于在給html元素進行化妝修整一樣。外邊距和內邊距就是屬于css的,用來控制html元素的外邊距和內邊距。margin分上下左右四個值,即margin-top,margin-bottom,margin-left,margin-right四個值。同樣padding也是一樣,有padding-top,......padding-right四個值。
講了這么多,我們可能還是不知道margin與padding到底是什么樣的。現在就來詳細地分享一下,為了更好的理解,在html里面,大家把所有html元素都看做盒子,每一個元素都看做一個盒子,這個也稱為css盒子模型。既然是盒子,那么一個盒子如果要和它右邊的盒子有個50像素的距離,就可以設置一個margin-right值為50px就行了,這個就是所謂的外邊距margin。而padding從中文意思,我們可以理解相當于給這個盒子弄了填塞料,填塞料的厚度就相當于內邊距padding的值了。另外提一下,盒子不單有margin和padding,還有一個border值,就是盒子厚度的意思,同樣有border-top......border-right上下左右四個值。最后用一個圖來看下盒子模型是怎么樣的,如下圖
解釋一下,圖中的content指的是盒子里面的內容,即html元素里面包含的內容。今天就講到這里了,更多內容大家關注點點有我,后面會繼續更新。有什么問題也可以留言一起討論一下哦
*請認真填寫需求信息,我們會在24小時內與您取得聯系。