1、[單選題] 有以下 ES6 代碼
function * gen() { yield 1; yield 2; yield 3; }
下面選項描述正確的是哪個?
A.gen()執行后返回 2
B.gen()執行后返回 undefined
C.gen()執行后返回一個 Generator 對象
D.gen()執行后返回 1
答案:C
提示:這是 ES6 的新 feature, function 后面帶 * 的叫做 generator function。函數運行時, 返回一個迭代器。
2、[不定項選擇題] 語句 var arr=[a,b,c,d];執行后,數組 arr 中每項都是一個整數,下面得到其中最大整數語 句正確的是哪幾項?
A.Math.max(arr)
B.Math.max(arr[0], arr[1], arr[2], arr[3])
C.Math.max.call(Math, arr[0], arr[1], arr[2], arr[3])
D.Math.max.apply(Math,arr)
答案:B C D
提示: A 選項錯誤
因為函數 Math.max(x);的參數是 Number 類型,可以使小數,整數,正數,負數或者是 0.如果不是上面所述類型就會返回 NaN.
3、[問答題] 寫一個 traverse 函數,輸出所有頁面寬度和高度大於 50 像素的節點。
<script language="javascript"> function traverse() { var arr = []; var elements = []; if (document.all) { elements = document.all; } else { elements = document.getElementsByTagName("*"); } for (var i = 0; i < elements.length; i++) { var ele = elements[i]; // width 返回的是字符串 offsetWidth 返回的是帶邊框的 Number 型的數字 var width = parseFloat(ele.style.width) || ele.offsetWidth; var height = parseFloat(ele.style.height) || ele.offsetHeight; if (width > 50 && height > 50) { arr.push(elements[i].tagName); } } return arr; } window.onload = function () { console.log(traverse()); console.log("a"); console.log('a'); } </script>
4、[問答題] 請寫一個表格以及對應的 CSS,使表格奇數行為白色背景,偶數行為灰色背景,鼠標移 上去時為黃色背景。
<table> <tr><td>第一行</td></tr> <tr><td>第二行</td></tr> <tr><td>第三行</td></tr> <tr><td>第四行</td></tr> <tr><td>第五行</td></tr> </table> table tr:nth-child(odd){ background-color: white; } table tr:nth-child(even){ background-color: gray; } table tr:hover{ background-color: yellow; }
5、[問答題] 寫一個求和的函數 sum,達到下面的效果
function sum() { var nResult = 0; for (var i = 0, l = arguments.length; i < l; i++) { nResult += window.parseFloat(arguments[i]) || 0; } return nResult.toFixed(3) * 1000 / 1000; }
6、[填空題] 刪除給定數組中的第二項和第三項,並且在得到的新的數組中第二項后面添加一個新的 值:
var arr1 = ['a','b','c','d','e'];
var arr2 = arr1. 1 ( 2 , 3 ,'newvalue')
var arr1 = ['a','b','c','d','e']; var arr2 = arr1.splice( 1,2 ,'newvalue') console.log(arr1);
7、[填空題] 在空白處填入適當的代碼使輸出結果成立:
function showMoney() { 1 }; var personA = new Object; var personB = new Object; personA.money = "100"; personB.money = "150"; personA.showMoney = showMoney; personB.showMoney = showMoney; // 輸出結果: personA.showMoney(); //"100" personB.showMoney(); //"150"
答案: return this.money
8、[填空題] 使用 for in 循環數組中的元素會枚舉原型鏈上的所有屬性,過濾這些屬性的方式是使 用 ? 函數
hasOwnProperty
9、[問答題] 請實現一個 fibonacci 函數,要求其參數和返回值如下所示:
/** * @desc: fibonacci * @param: count {Number} * @return: result {Number} * 第 count 個 fibonacci 值,計數從 0 開始 * fibonacci 數列為:[1, 1, 2, 3, 5, 8, 13, 21, 34 „] * 則 getNthFibonacci(0)返回值為 1 * 則 getNthFibonacci(4)返回值為 5 */ function getNthFibonacci(count) { if (count <= 1) { return 1; } return getNthFibonacci(count - 1) + getNthFibonacci(count - 2); }
10、[填空題]
輸出對象中值大於 2 的 key 的數組
var data = {a: 1, b: 2, c: 3, d: 4};
Object.keys(data).filter(function(x) { return ? ;})
期待輸出:[“c”,”d”]
答案: data[x] > 2
11、[填空題] 填寫內容讓下面代碼支持 a.name = “name1”; b.name = “name2”;
function obj(name) { if(name){ this.name = name } return this } obj.prototype.name = "name2"; var a = obj("name1"); var b = new obj;
12、JavaScript語言特性中,有很多方面和我們接觸的其他編程語言不太一樣,比如說,JavaScript語言實現繼承機制的核心就是 《prototype》,而不是Java語言那樣的類式繼承。JavaScript解析引擎在讀取一個 Object 的屬性的值時,有沿着《原型鏈》向上尋找,如果最終沒有找到,則該屬性值為《undefined》;如果最終找到該屬性的值,則返回結果。與這個過程不同的是,當JavaScript解析引擎執行“給一個Object的某個屬性賦值”的時候,如果當前Object存在該屬性,則改寫該屬性的值,如果當前的Object本身並不存在該屬性,則賦值該屬性的值。
13、[單選題] 下面有關 html 的描述,不推薦的是?
A.在頁面頂部添加 doctype 聲明;
B.在 </head> „ <body> 中間插入 HTML 代碼;
C.避免使用 <font> 標簽;
D.使用 <table> 元素展現學生成績表等數據。
答案:B
14、[單選題] 下面關於 CSS 布局的描述,不正確的是?
A.塊級元素實際占用的寬度與它的 width 屬性有關;
B.塊級元素實際占用的寬度與它的 border 屬性有關;
C.塊級元素實際占用的寬度與它的 padding 屬性有關;
D.塊級元素實際占用的寬度與它的 background 屬性有關。
答案:D
15:、[單選題]下列事件哪個不是由鼠標觸發的事件()
A.click
B.contextmenu
C.mouseout
D.keydown
答案:D
16、[問答題] 請說說 cache-control 是怎么回事?
網頁的緩存是有 HTTP 消息頭中的 “Cache-control” 來控制的,常見的取值有 private 、no-cache、max-age、must-revalidate 等,默認為 private
Expires 頭部字段提供一個日期和時間,響應在該日期和時間后被認為失效。允許客戶端在這個時間之前不去檢查(發請求),等同 max-age 的效果。但是如果同時存在,則被 Cache-Control 的 max-age 覆蓋
Expires = "Expires" : "HTTP-date"
例如: Expires: Thu,01 Dec 1994 16:00:00 GMT (必須是GMT格式)
如果把它設置為-1,則表示立即過期
Expires 和 max-age 都可以用來指定文檔的過期時間,但是二者有一些細微差別
1.Expires 在 HTTP/1.0 中已經定義,Cache-Control:max-age 在HTTP/1.1中才有定義,為了向下兼容,僅使用 max-age不夠。
2.Expires 指定一個絕對的過期時間(GMT 格式),這么做會導致至少 2 個問題:
2.1 客戶端和服務器時間不同步導致 Expires 的配置出現問題。
2.2 很容易在配置后忘記具體的過期時間,導致過期來臨出現浪涌現象
3. max-age 指定的是從文檔被訪問后的存活時間,這個時間是個相對值(比如:3600s), 相對的是文檔第一次被請求時服務器記錄的 Request_time(請求時間)
4. Expires 指定的時間可以是相對文件的最后訪問時間(Atime)或者修改時間(MTime),而 max-age 相對對的是文檔的請求時間(Atime)
5.如果值為 no-cache,那么每次都會訪問服務器。如果值為 max-age,則在過期之前不 會重復訪問服務器。
17、[問答題] 你了解 HTTP 狀態碼嗎,請隨便介紹一下。
100 Continue 繼續,一般在發送 post 請求時,已發送了 http header 之后服務端將返回 此信息,表示確認,之后發送具體參數信息
200 OK 正常返回信息
201 Created 請求成功並且服務器創建了新的資源
202 Accepted 服務器已接受請求,但尚未處理
301 Moved Permanently 請求的網頁已永久移動到新位置
302 Found 臨時性重定向
303 See Other 臨時性重定向,且總是使用 GET 請求新的 URI
304 Not Modified 自從上次請求后,請求的網頁未修改過
400 Bad Request 服務器無法理解請求的格式,客戶端不應當嘗試再次使用相同的內容 發起請求
401 Unauthorized 請求未授權
403 Forbidden 禁止訪問
404 Not Found 找不到如何與 URI 相匹配的資源
500 Internal Server Error 最常見的服務器端錯誤
503 Service Unavailable 服務器端暫時無法處理請求(可能是過載或維護)
18、[問答題] 如何獲取 UA?
通過JS獲取瀏覽器UA(User Agent,用戶代理)
//獲取完整的瀏覽器名稱 document.Browser.Name.value=navigator.appName; //獲取瀏覽器的版本,一般不與實際的瀏覽器版本對應 document.Browser.Version.value=navigator.appVersion; //獲取瀏覽器的名稱。通常都是Mozilla,即使在非Mozilla的瀏覽器中也是如此 document.Browser.Code.value=navigator.appCodeName; //獲取瀏覽器的用戶代理字符串 document.Browser.Agent.value=navigator.userAgent;
19、[問答題] 說說對網站重構的理解。
網站重構:在不改變外部行為的前提下,簡化結構、添加可讀性,而在網站前端保持一致性的行為。也就是說在不改變UI的情況下,對網站進行優化,在擴展的同時保持一致性的UI
對於傳統的網站來說,重構通常是:
(1)表格(table)布局改為 DIV + CSS
(2)使網頁前端兼容於現代瀏覽器(針對於不合規范的CSS、如對 IE6 有效的)
(3)對於移動平台的優化
(4)針對SEO進行優化
(5)深層次的網站重構應該考慮的方面
(6)減少代碼的耦合
(7)讓代碼保持彈性
(8)嚴格按規范編寫代碼
(9)設計可擴展的API
(10)代替舊有的框架、語言
(11)增強用戶體驗
(12)通常來說對於速度的優化也包含在重構中
(13)壓縮JS、CSS、image 等前端資源(通常是由服務器來解決的)
(14)程序的性能優化(如數據讀寫)
(15)采用CDN來加速資源加載
(16)對於 JS DOM 的優化
(17)HTTP服務器的文件緩存
SEO:(Search Engine Optimization):漢譯為搜索引擎優化。是一種方式:利用搜索引擎的規則提高網站在有關搜索引擎內的自然排名。
function clone(obj) { let ret if (Array.isArray(obj)) { ret = [] // 創建一個空數組 for (let i = 0; i < obj.length; i++) { ret[i] = clone(obj[i]) } return ret } else if (Object.prototype.toString.call(obj) === "[object Object]") { ret = {} // 創建一個空對象 for (let i in obj) { ret[i] = clone(obj[i]) } return ret } else { return obj } }
21、[問答題] Ajax 是什么?Ajax 的交互模型?同步和異步的區別?如何解決跨域問題?
(1)ajax 的全稱是異步的 JavaScript 和 XML ,是一種創建快速動態的技術,通過在后台與服務器進行少量數據交互,實現網頁的異步更新,在不重新加載整個界面的情況下,做到網頁的部分刷新
(2)ajax的交互模型(ajax的過程)
- 用戶發出異步請求
- 創建 XMLHttpRequest 對象
- 告訴 XMLHttpRequest 對象哪個函數會處理 XMLHttpRequest 對象狀態的改變,為此要把對象的 onReadyStateChange 屬性設置為響應該事件的 JavaScript 函數的引用
- 創建請求,用 open 方法指定是get還是post,是否異步,url地址
- 發送請求,send方法
- 接收結果並分析
- 實現刷新
(3)同步和異步的區別:
- 同步:腳本會停留並等待服務器發送回復然后在繼續
- 異步:腳本允許頁面繼續其進程並處理可能的回復
(4)跨域問題的解決:
- 使用 document.domain + iframe 解決跨子域問題
- 使用 window.name
- 使用 flash
- 使用 iframe + location.hase
- 使用 html5 的 postMessage
- 使用 jsonp (創建動態 script)
22、[問答題] IE 與火狐的事件機制有什么區別? 如何阻止冒泡?
(1)我們在網頁中的某個操作(有的操作對應多個事件)。例如:當我們點擊一個按鈕就會產生一個事件。是可以被JavaScript偵測到的行為
(2)事件處理機制:IE是事件冒泡,firefox 同時支持兩種事件模型(捕獲型事件和冒泡型事件)
(3)ev.stopPropagation() ---注意舊 ie 的方法:ev.cancelBubble = true
23、[問答題] WEB 應用從服務器主動推送 Data 到客戶端有那些方式?
(1)html5 websoket
(2)websocket 通過 flash
(3)XHR 長時間連接
(4)XHR Multipart Streaming
(5)不可見的 Iframe
(6)<sctipt>標簽的長時間連接(可跨域)
24、[問答題] JavaScript 原型,原型鏈 ? 有什么特點?
(1)原型對象也是普通的對象,是對象一個自帶隱式的 __proto__ 屬性,原型也有可能有自己的原型,如果一個原型對象的原型不為 null 的話,我們就稱之為原型鏈
(2)原型鏈是由一些用來繼承和共享屬性的對象組成的(有限的)對象鏈
25、[問答題] Node.js 的適用場景
(1)高並發
(2)聊天
(3)實時消息推送
26、[問答題] eval 是做什么的,有什么建議?
(1)它的功能是把對應的字符串解析成 JS 代碼並運行
(2)應該避免使用eval,不安全,非常耗性能(2次,一次解析成js語句,一次執行)
27、[問答題] 哪些地方會出現 css 阻塞,哪些地方會出現 js 阻塞?
- 當CSS后面跟着嵌入的JS的時候,該CSS就會出現阻塞后面資源下載的情況;
- 而當把嵌入JS放到CSS前面,就不會出現阻塞的情況了。
- 因為瀏覽器會維持html中css和js的順序,樣式表必須在嵌入的JS執行前先加載、解析完。
- 而嵌入的JS會阻塞后面的資源加載,所以就會出現上面CSS阻塞下載的情況。
- 放在底部,雖然放在底部照樣會阻塞所有呈現,但不會阻塞資源下載。
- 如果嵌入JS放在head中,請把嵌入JS放在CSS頭部。
- 使用defer(只支持IE)
- 不要在嵌入的JS中調用運行時間較長的函數,如果一定要用,可以用`setTimeout`來調用
28、[問答題] GET 和 POST 的區別,何時使用 POST?
GET:一般用於信息獲取,使用URL傳遞參數,對所發送的信息數量有限制,一般在 2000 個字符
POST:一般用於修改服務器上的資源,對所發送的信息沒有限制
GET方式需要使用 Request.QueryString 來取得變量的值
POST方式通過 Request.Form 來獲取變量的值
也就是說Get是通過地址欄來傳值,而Post是通過提交表單來傳值
在以下情況下,使用POST請求:
(1)無法使用緩存文件(更新服務器上的文件或數據庫)
(2)向服務器發送大量數據(POST沒有數據量限制)
(3)發送包含未知字符的用戶輸入時,POST比GET更穩定也更可靠
29、[問答題] 請解釋一下 JavaScript 的同源策略。
同源策略是客戶端腳本(尤其是JavaScript)的重要安全度量標准。其目的是防止某個文檔或腳本從多個不同源裝載。
這里的同源策略指的是:協議、域名、端口號相同,同源策略是一種安全協議,指一段腳本只能讀取來自同一來源的窗口和文檔的屬性。
為什么要有同源限制:
我們舉例說明:比如一個黑客程序,他利用 Iframe 把真正的銀行登錄頁面嵌入他的頁面上,當你使用真實的用戶名、密碼登錄時,他的頁面就可以通過JavaScript讀取到你的表單中input中的內容,這樣用戶名、密碼就輕松到手了。
30、[問答題] 什么叫優雅降級和漸進增強?
(1)優雅降級:Web站點在所有新式瀏覽器中都能正常工作,如果用戶使用的是老式瀏覽器,則代碼會檢查以確認它們是否能正常工作。由於 IE 獨特的盒模型布局問題,針對不同版本的 IE 的 hack實踐過優雅降級了,為那些無法支持功能的瀏覽器增加候選方案,使之在舊式瀏覽器上以某種形式降級體驗卻不至於完全失效。
(2)漸進增強:從被所有瀏覽器支持的基本功能開始,逐步地添加那些只有新式瀏覽器才支持的功能,向頁面增加無害於基礎瀏覽器的額外樣式和功能。當瀏覽器支持時,它們會自動地呈現出來並發揮作用。
31、[問答題] 哪些操作會造成內存泄漏?
內存泄漏指任何對象在你不在擁有或需要它之后仍然存在。
垃圾回收器定期掃描對象,並計算引用了每個對象的其他對象的數量。如果一個對象的引用為0(沒有其他對象引用過該對象),或對該對象的唯一引用是循環的,那么該對象的內存即可回收。
(1)setTimeout 的第一個參數使用字符串而非函數的話,會引發內存泄漏
(2)閉包
(3)控制台日志
(4)循環引用(在兩個對象彼此引用且彼此保留時,就會產生一個循環引用)
32、[問答題] .call() 和 .apply() 的作用?
動態改變某個類的某個方法的運行環境
33、[單選題]
function Foo() { var i = 0; return function () { document.write(i++); } } var f1 = Foo(), f2 = Foo(); f1(); f1(); f2();
請問以上程序的輸出是()
var a = "undefined"; var b = "false"; var c = ""; function assert(aVar) { if (aVar) alert(true); else alert(false); } assert(a); assert(b); assert(c);
// 方法1 function indexOf(str, subStr){ var ret = str.match(subStr) return ret ? ret.index : -1 } // 方法2 function indexOf(a, b){ return a.search(b) }
36、[單選題]
var myObject = { foo: "bar", func: function () { var self = this; console.log(this.foo); console.log(self.foo); (function () { console.log(this.foo); console.log(self.foo); }()); } }; myObject.func();
程序的輸出是什么?
console.log(1 + "2" + "2"); console.log(1 + +"2" + "2"); console.log("A" - "B" + "2"); console.log("A" - "B" + 2);
function f1() { var n = 100; nAdd = function () { n += 1 } function f2() { alert(n); } return f2; } var result = f1(); result(); nAdd(); result();
輸出:100 undefined 100
45、什么樣的請求是簡單請求?
請求方法是以下三種方法之一:
- HEAD
- GET
- POST
HTTP的請求頭信息不超出以下幾種字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限於三個值 application/x-www-form-urlencoded、multipart/form-data、text/plain
46、能說說首屏加載優化有哪些方案嗎?
- Vue-Router路由懶加載(利用Webpack的代碼切割)
- 使用CDN加速,將通用的庫從vendor進行抽離
- Nginx的gzip壓縮
- Vue異步組件
- 服務端渲染SSR
- 如果使用了一些UI庫,采用按需加載
- Webpack開啟gzip壓縮
- 如果首屏為登錄頁,可以做成多入口
- Service Worker緩存文件處理
- 使用link標簽的rel屬性設置 prefetch(這段資源將會在未來某個導航或者功能要用到,但是本資源的下載順序權重比較低,prefetch通常用於加速下一次導航)、preload(preload將會把資源的下載順序權重提高,使得關鍵數據提前下載好,優化頁面打開速度)
47、談談你對作用域鏈的理解
了解作用域鏈之前我們要知道以下幾個概念:
- 函數的生命周期
- 變量和函數的聲明
- Activetion Object(AO)、Variable Object(VO)
函數的生命周期:
- 創建:JS解析引擎進行預解析,將函數聲明提前,同時將該函數放到全局作用域或當前函數的上一級函數的局部作用域中。
- 執行:JS引擎會將當前函數的局部變量和內部函數進行聲明提前,然后再執行業務代碼,當函數執行完退出時,釋放該函數的執行上下文,並注銷該函數的局部變量。
變量和函數的聲明:如果變量名和函數名聲明時相同,函數優先聲明
Activetion Object(AO)、Variable Object(VO):
- AO:Activetion Object(活動對象)
- VO:Variable Object(變量對象)
VO對應的是函數創建階段,JS解析引擎進行預解析時,所有的變量和函數的聲明,統稱為 Variable Object。該變量與執行上下文相關,知道自己的數據存儲在哪里,並且知道如何訪問。VO是一個與執行上下文相關的特殊對象,它存儲着在上下文中聲明的以下內容:
- 變量(var,變量聲明)
- 函數聲明(FunctionDeclaration)
- 函數的形參
AO對應的是函數執行階段,當函數被調用執行時,會建立一個執行上下文,該執行上下文包含了函數所需的所有變量,該變量共同組成了一個新的對象就是Activetion Object。該對象包含了:
- 函數的所有局部變量
- 函數的所有命名參數
- 函數的參數集合
- 函數的this指向
作用域鏈:
當代碼在一個環境中創建時,會創建變量對象的一個作用域鏈來保證對執行環境有權訪問的變量和函數。作用域第一個對象始終是當前執行代碼所在環境的變量對象(VO)。如果是函數執行階段,那么將其AO作為作用域鏈第一個對象,第二個對象是上級函數的執行上下文AO,下一個對象依次類推。
當查找變量的時候,會先從當前上下文的變量對象中查找,如果沒有找到,就會從父級(詞法層面上的父級)執行上下文的變量對象中查找,一直找到全局上下文的變量對象,也就是全局對象。這樣由多個執行上下文的變量對象構成的鏈表就叫做作用域鏈。
48、在ES5中如何實現繼承
寄生組合式繼承:
所謂寄生組合式繼承,及通過借用構造函數來繼承屬性,通過原型鏈的混和形式來繼承方法。其背后的基本思想是:不必為了指定子類型的原型而調用超類型的構造函數,我們所需要的無非就是超類型原型的一個副本而已。本質上,就是使用寄生式繼承來繼承超類型的原型,然后再將結果指定給子類型的原型。
49、絕對定位
如果不設置子元素 left top的話,absolute的子元素是頂在父元素的 content左上方的
如果設置子元素 left = 0 top = 0 的話,子元素是頂在父元素的 padding 左上方的(在border內)
- 一旦給元素加上了 absolute 或 float 就相當於給元素加上了 display: block
- absolute 元素覆蓋正常文檔流內元素(不用設 z-index,自然覆蓋)
- 可以減少重繪和回流的開銷(如 absolute + top:-9999em,或 absolute + visibility:hidden,將動畫效果放到 absolute 元素中)
屬性介紹:
- static:默認值,位置設置為 static 的元素,它始終會處於文檔流給予的位置。
- inherit:規定應該從父元素繼承 position 屬性的值。但是任何版本的 IE 都不支持屬性值 “inherit”
- fixed:生成絕對定位的元素。默認情況下,可定位於相對於瀏覽器窗口的指定坐標。但當祖先元素具有 transform 屬性且不為 none 時,就會相對於祖先元素指定坐標,而不是瀏覽器窗口。
- absolute:生成絕對定位的元素,相對於該元素最近的已定位的祖先元素進行定位。
- relative:生成相對定位的元素,相對於該元素在文檔中的初始位置進行定位。
浮動、絕對定位和固定定位會脫離文檔流,相對定位不會脫離文檔流,絕對定位相對於該元素最近的已定位的祖先元素,如果沒有一個祖先元素設置定位,那么參照物是body
- 如果祖先元素是塊級元素,包含塊則設置為該元素的內邊距邊界
- 如果祖先元素是行內元素,包含塊則設置為該祖先元素的內容邊界
問答題:
- 定位的元素的起始位置為父包含塊的內邊距(不會在border里,除非使用負值,會在padding里)
- 定位的元素的margin還是能起作用的
- background屬性是會顯示在border里的
- z-index是由層疊層級的,需要考慮同一個層疊上下文的層疊優先級
- z-index是負值不會覆蓋包含塊的背景色(但是如果有內容,會被包含塊的內容覆蓋)
- z-index的值影響的元素是定位元素以及flex盒子
- 上面一個定位元素,下面一個正常流的元素,定位元素會覆蓋在正常流元素之上,除非給z-index是負值
- 頁面根元素html天生具有層疊上下文,稱之為“根層疊閃現給我”
50、講講MVVM,說說與MVC有什么區別?
MVC允許在不改變視圖的情況下改變視圖對用戶輸入的響應方式,用戶對View的操作交給了Controller處理,在Controller中響應View的事件調用Model的接口對數據進行操作,一旦Model發生變化便通知相關視圖進行更新。
如果前端沒有框架,只使用原生的 html+js,MVC模式可以這樣理解。將html看作view;js看作controller,負責處理用戶與應用的交互,響應對view的操作(對事件的監聽),調用Model對數據進行操作,完成model與view的同步(根據model的改變,通過選擇器對view進行操作);將js的ajax當做Model,也就是數據層,通過ajax從服務器獲取數據。
Model看成模型,View看成這個模型的視圖化體現,而Controller根據需要寫在各自的方法里。
MVVM與MVC最大的區別就是:它實現了View和Model的自動同步,也就是當Model的屬性改變時,我們不用再自己手動操作DOM元素,來改變View的顯示,而是改變屬性后該屬性對應View層會自動改變。
從整體來看,MVVM比MVC精簡很多,不僅簡化了業務與界面的依賴,還解決了數據頻繁更新的問題,不用再使用選擇器操作DOM元素。因為在MVVM中,View不知道Model的存在,Model和ViewModel也觀察不到View,這種低耦合模式提高代碼的可重用性。
51、說說事件委托有什么好處?
事件委托就是利用事件冒泡機制指定一個事件處理程序,來管理某一類型的所有事件。
即:利用冒泡的原理,把事件加到父級上,觸發執行效果。
好處:
- 只在內存中開辟了一塊空間,節省資源同時減少了DOM操作,提供性能
- 對於新添加的元素也會有之前的事件
52、target和currentTarget的區別
- target在事件流的目標階段
- currentTarget在事件流的捕獲、目標及冒泡階段
只有當事件流處於目標階段的時候,兩個的指向才是一樣的,而處於捕獲和冒泡階段的時候,target指向被單擊的對象,而currentTarget指向當前事件活動的對象(注冊該事件的對象,一般為父級)。
53、Service Worker的作用
- 網絡代理,轉發請求,偽造響應
- 離線緩存
- 消息推送
- 后台消息傳遞
54、如何判斷兩個變量相等
Object.is()方法判斷兩個值是否是相同的值
NaN === NaN // false
+0 === -0 // true
Object.is(NaN, NaN) // true
Object.is(+0, -0) // false
在ES5中實現 Object.is() 的 polyfill
if (!Object.is) { Object.is = function(x, y) { if (x === y) { // Steps 1-5, 7-10 // 針對 +0不等於-0 return x !== 0 || 1 / x === 1 / y; } else { // 針對 NaN等於NaN return x !== x && y !== y; } }; }