1. 最簡單的一道題
'11' * 2 'a8' * 3 var a = 2, b = 3; var c = a+++b; // c = 5
2. 一道this的問題
var num = 10; var obj = { num:8, inner: { num: 6, print: function () { console.log(this.num); } } } num = 888; obj.inner.print(); // 6 var fn = obj.inner.print; fn(); //888 (obj.inner.print)(); //6 (obj.inner.print = obj.inner.print)(); //888 這個點沒有太理解,雖然答對了
3. var和function的預解析問題,以及變量和function的先后順序的問題
// 以下代碼執行輸出結果是什么 function b () { console.log(a); var a = 10; function a() {}; a = 100; console.log(a); } b(); function c () { console.log(a); function a() {}; var a = 10; a = 100; console.log(a); } c(); (function d (num) { console.log(num); var num = 10; }(100)) (function e (num) { console.log(num); var num = 10; function num () {}; }(100)) (function f (num) { function num () {}; console.log(num); var num =10 console.log(num); }(100)) //仍然是預解析(在與解析過程中還要考慮一下當前變量的作用於) function m () { console.log(a1); // underfined console.log(a2); // underfined console.log(b1); // underfined console.log(b2); // underfined if(false) { function b1 (){}; var a1 = 10; } if(true) { function b2 (){}; var a2 = 10; } console.log(a1); // underfined console.log(a2); // 10 console.log(b1); // underfined console.log(b2); // function } m(); function n() { if(2>1) { arr = 10; brr = 10; let arr; var brr; console.log(arr); console.log(brr); } } n(); // ReferenceError
此階段瀏覽器只是對var、function、函數形參進行一個解析的准備過程。而且在這個“預解析”過程中,有一個預解析先后順序,即函數的形參 -> function -> var。而且重名時預留函數、后來者覆蓋前者。預解析結果形參如果有值則解析到值,沒有則為underfined,函數則解析到整個函數體,變量都為underfined;這道題目中沒有參數出現,所以先不討論。所以這道題在“預解析”時,函數聲明權重優先會被提升
4. 一個算法問題
有一個已經排序的數組,比方[1,4,6,9,11,15,18],給你一個新的數,插入到數組中,寫一個function
5. 函數節流是什么,有什么優點(之前沒有了解過這個概念,懵逼了)
函數節流的目的
從字面上就可以理解,函數節流就是用來節流函數從而一定程度上優化性能的。例如,DOM 操作比起非DOM 交互需要更多的內存和CPU 時間。連續嘗試進行過多的DOM 相關操作可能會導致瀏覽器掛起,有時候甚至會崩潰。尤其在IE 中使用onresize 事件處理程序的時候容易發生,當調整瀏覽器大小的時候,該事件會連續觸發。在onresize 事件處理程序內部如果嘗試進行DOM 操作,其高頻率的更改可能會讓瀏覽器崩潰。又例如,我們常見的一個搜索的功能,我們一般是綁定keyup事件,每按下一次鍵盤就搜索一次。但是我們的目的主要是每輸入一些內容搜索一次而已。為了解決這些問題,就可以使用定時器對函數進行節流。
函數節流的原理
某些代碼不可以在沒有間斷的情況連續重復執行。第一次調用函數,創建一個定時器,在指定的時間間隔之后運行代碼。當第二次調用該函數時,它會清除前一次的定時器並設置另一個。如果前一個定時器已經執行過了,這個操作就沒有任何意義。然而,如果前一個定時器尚未執行,其實就是將其替換為一個新的定時器。目的是只有在執行函數的請求停止了一段時間之后才執行。
http://www.cnblogs.com/LuckyW...
6. 寫一個方法,實現傳入兩個參數(parentNode, childNode),要求如果childNode是parentNode的子孫節點,則返回為true,否則返回為false
7. dom事件流原理是什么,分為那幾個階段?
事件捕獲 處於目標階段 事件冒泡
8. dom事件委托什么原理,有什么優缺點
事件委托原理:事件冒泡機制
優點
1.可以大量節省內存占用,減少事件注冊。比如ul上代理所有li的click事件就很不錯。
2.可以實現當新增子對象時,無需再對其進行事件綁定,對於動態內容部分尤為合適
缺點
事件代理的常用應用應該僅限於上述需求,如果把所有事件都用事件代理,可能會出現事件誤判。即本不該被觸發的事件被綁定上了事件。
9. http的cache機制,以及200狀態下怎么實現 from cache(表示接觸最多的就是304的from cache)(用於優化,沒有接觸過,需要理解)
含義
定義:瀏覽器緩存(Browser Caching)是為了加速瀏覽,瀏覽器在用戶磁盤上對最近請求過的文檔進行存儲,當訪問者再次請求這個頁面時,瀏覽器就可以從本地磁盤顯示文檔,這樣就可以加速頁面的閱覽。
作用
cache的作用:
1、減少延遲,讓你的網站更快,提高用戶體驗。
2、避免網絡擁塞,減少請求量,減少輸出帶寬。
實現手段
Cache-Control中的max-age是實現內容cache的主要手段,共有3種常用策略:max-age和Last-Modified(If-Modified-Since)的組合、僅max-age、max-age和ETag的組合。
對於強制緩存,服務器通知瀏覽器一個緩存時間,在緩存時間內,下次請求,直接用緩存,不在時間內,執行比較緩存策略。
對於比較緩存,將緩存信息中的Etag和Last-Modified通過請求發送給服務器,由服務器校驗,返回304狀態碼時,瀏覽器直接使用緩存。
10. 一個原型鏈繼承的問題
// 有一個構造函數A,寫一個函數B,繼承A function A (num) { this.titileName = num; } A.prototype = { fn1: function () {}, fn2: function () {} }
這個問題的關注點是B繼承的A的靜態屬性,同時B的原型鏈中不存在A實例的titleName屬性
11. 什么是虛擬dom
React為啥這么大?因為它實現了一個虛擬DOM(Virtual DOM)。虛擬DOM是干什么的?這就要從瀏覽器本身講起
如我們所知,在瀏覽器渲染網頁的過程中,加載到HTML文檔后,會將文檔解析並構建DOM樹,然后將其與解析CSS生成的CSSOM樹一起結合產生愛的結晶——RenderObject樹,然后將RenderObject樹渲染成頁面(當然中間可能會有一些優化,比如RenderLayer樹)。這些過程都存在與渲染引擎之中,渲染引擎在瀏覽器中是於JavaScript引擎(JavaScriptCore也好V8也好)分離開的,但為了方便JS操作DOM結構,渲染引擎會暴露一些接口供JavaScript調用。由於這兩塊相互分離,通信是需要付出代價的,因此JavaScript調用DOM提供的接口性能不咋地。各種性能優化的最佳實踐也都在盡可能的減少DOM操作次數。
而虛擬DOM干了什么?它直接用JavaScript實現了DOM樹(大致上)。組件的HTML結構並不會直接生成DOM,而是映射生成虛擬的JavaScript DOM結構,React又通過在這個虛擬DOM上實現了一個 diff 算法找出最小變更,再把這些變更寫入實際的DOM中。這個虛擬DOM以JS結構的形式存在,計算性能會比較好,而且由於減少了實際DOM操作次數,性能會有較大提升
12. js基礎數據類型和引用類型分別是什么?這個前提條件下寫一個getType,返回相應的類型
1.基本數據類型(自身不可拆分的):Undefined、Null、Boolean、Number、String
2.引用數據類型(對象):Object (Array,Date,RegExp,Function)
ES6基本數據類型多了個symbol 據說這道題刷了百分之二十的人 感謝Abbyshen提出
function gettype(nm){ return Object.prototype.toString.call(nm); }
13. dom選擇器優先級是什么,以及權重值計算(一道老問題了)
1.行內樣式 1000
2.id 0100
3.類選擇器、偽類選擇器、屬性選擇器[type="text"] 0010
4.標簽選擇器、偽元素選擇器(::first-line) 0001
5.通配符*、子選擇器、相鄰選擇器 0000
14. vue雙向數據綁定的原理是什么
首先傳輸對象的雙向數據綁定 Object.defineProperty(target, key, decription),在decription中設置get和set屬性(此時應注意description中get和set不能與描述屬性共存)
數組的實現與對象不同。
同時運用觀察者模式實現wather,用戶數據和view視圖的更新
15. react和vue比較來說有什么區別
1 component層面,web component和virtual dom
2 數據綁定(vue雙向,react的單向)等好多
3 計算屬性 vue 有,提供方便;而 react 不行
4 vue 可以 watch 一個數據項;而 react 不行
5 vue 由於提供的 direct 特別是預置的 directive 因為場景場景開發更容易;react 沒有
6 生命周期函數名太長 directive
16. git使用過程中,如果你在開發着業務,突然另一個分支有一個bug要改,你怎么辦
git stash //將本次修改存到暫存區(緊急切換分支時) git stash pop //將所有暫存區的內容取出來
17. postcss的使用
18. 網頁布局有哪幾種,有什么區別
靜態、自適應、流式、響應式四種網頁布局
靜態布局:意思就是不管瀏覽器尺寸具體是多少,網頁布局就按照當時寫代碼的布局來布置;
自適應布局:就是說你看到的頁面,里面元素的位置會變化而大小不會變化;
流式布局:你看到的頁面,元素的大小會變化而位置不會變化——這就導致如果屏幕太大或者太小都會導致元素無法正常顯示。
自適應布局:每個屏幕分辨率下面會有一個布局樣式,同時位置會變而且大小也會變。
18. 執行下面代碼
var a = {}; var b = {key: 'b'}; var c = {key: 'c'}; var d = [3,5,6]; a[b] = 123; a[c] = 345; a[d] = 333; console.log(a[b]); // 345 console.log(a[c]); // 345 console.log(a[d]); // 333
19.
var R = (function() { var u = {a:1,b:2}; var r = { fn: function(k) { return u[k]; } } return r; }()); R.fn('a'); // 1
上述代碼中如何獲取匿名函數中的u
20. 不適用循環語句(包括map、forEach方法)實現一個100長度的數組,索引值和值相同的數組[0,1,2,3,4,5........99]
var arr = new Array(100); //方法1 [...arr.keys()]; //方法二 Array.from(arr.keys()); //方法三 Array.from({length: 100}); // 方法四 借助string var arr1 = new Array(101); var str = arr1.join('1,'); str = str.replace(/(1\,)/g, function ($0, $1, index) { var start = '' + Math.ceil(index/2); if(index < str.length - 2) { start += ',' } return start; }); return str.split(','); // 方法五(函數式,參考網絡) function reduce(arr, val) { if(Object.prototype.toString.apply(val)){ return; } if(val >= 100) { return arr; } arr.push(val); return reduce(arr, val+1); } var res = reduce([], 0)
21. 下面語句執行結果輸出
var a = function (val, index) { console.log(index); return { fn: function (name) { return a(name, val); } } } var b = a(0); // underfined b.fn(1); // 0 b.fn(2); // 0 b.fn(3); // 0
22. 科普
1) dom節點的根節點是不是body
回答: 不是,dom節點的根節點是html(包含head和body,head中分為meta、title等。body又分為一組)
2)dom元素都會有offsetParent嗎
回答: offsetParent屬性返回一個對象的引用,這個對象是距離調用offsetParent的元素最近的(在包含層次中最靠近的),並且是已進行過CSS定位的容器元素。 如果這個容器元素未進行CSS定位, 則offsetParent屬性的取值為根元素(在標准兼容模式下為html元素;在怪異呈現模式下為body元素)的引用。 當容器元素的style.display 被設置為 "none"時(譯注:IE和Opera除外),offsetParent屬性 返回 null。
3) [1,3,5]轉譯成字符串是什么
回答: '1,3,5'
調用toString方法,生成該字符串
4)li標簽的祖級元素可以為li,父級元素也可以為例
回答: 錯誤
23. jsonp原理,jquery是怎么實現的,這樣實現有什么好處和壞處
原理
在同源策略下;在某個服務器下的頁面是無法獲取到該服務器以外的數據的;Jquery中ajax 的核心是通過 XmlHttpRequest獲取非本頁內容,而jsonp的核心則是動態添加 <script>標簽來調用服務器提供的 js腳本
當我們正常地請求一個JSON數據的時候,服務端返回的是一串 JSON類型的數據,而我們使用 JSONP模式來請求數據的時候服務端返回的是一段可執行的 JavaScript代碼。因為jsonp 跨域的原理就是用的動態加載 script的src ,所以我們只能把參數通過 url的方式傳遞, 所以jsonp的 type類型只能是get !
$.ajax({
url: 'http://192.168.1.114/yii/demos/test.php', //不同的域 type: 'GET', // jsonp模式只有GET 是合法的 data: { 'action': 'aaron' }, dataType: 'jsonp', // 數據類型 jsonp: 'backfunc', // 指定回調函數名,與服務器端接收的一致,並回傳回來 }) 其實jquery 內部會轉化成 http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron 然后動態加載 <script type="text/javascript"src="http://192.168.1.114/yii/demos/test.php?backfunc=> 然后后端就會執行backfunc(傳遞參數 ),把數據通過實參的形式發送出去。
在jquery 源碼中, jsonp的實現方式是動態添加<script>標簽來調用服務器提供的 js腳本。jquery 會在window對象中加載一個全局的函數,當 <script>代碼插入時函數執行,執行完畢后就 <script>會被移除。同時jquery還對非跨域的請求進行了優化,如果這個請求是在同一個域名下那么他就會像正常的 Ajax請求一樣工作。
24. http協議屬於七層協議中的哪一層,下一層是什么
七層結構:物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層
tcp屬於傳輸層;http屬於應用層。
表現層
25. js垃圾回收機制知道哪些,v8引擎使用的哪一種
js的兩種回收機制
1 標記清除(mark and sweep)
2 引用計數(reference counting)
javascript與V8引擎
垃圾回收機制的好處和壞處
好處:大幅簡化程序的內存管理代碼,減輕程序猿負擔,並且減少因為長時間運轉而帶來的內存泄露問題。
壞處:自動回收意味着程序猿無法掌控內存。ECMAScript中沒有暴露垃圾回收的借口,我們無法強迫其進行垃圾回收,更加無法干預內存管理。
V8 自動垃圾回收算法
https://segmentfault.com/a/11...
26. 作用域什么時候生成的?
頁面加載-->創建window全局對象,並生成全局作用域-->然后生成執行上下文,預解析變量(變量提升),生成全局變量對象;
$scope
27. websocket長連接原理是什么
含義
Websocket是一個持久化的協議,相對於HTTP這種非持久的協議來說。
原理
類似長輪循長連接 ; 發送一次請求 ; 源源不斷的得到信息
28. http緩存知道哪些
http://blog.csdn.net/yzf91321...
29. 講一下事件循環機制
執行上下文(Execution context)
函數調用棧(call stack)
隊列數據結構(queue)
Promise
https://zhuanlan.zhihu.com/p/...
30. 理解web安全嗎?都有哪幾種,介紹以及如何預防
1.XSS,也就是跨站腳本注入
攻擊方法:
1. 手動攻擊:
編寫注入腳本,比如”/><script>alert(document.cookie());</script><!--等, 手動測試目標網站上有的input, textarea等所有可能輸入文本信息的區域 2. 自動攻擊 利用工具掃描目標網站所有的網頁並自動測試寫好的注入腳本,比如:Burpsuite等 防御方法: 1. 將cookie等敏感信息設置為httponly,禁止Javascript通過document.cookie獲得 2. 對所有的輸入做嚴格的校驗尤其是在服務器端,過濾掉任何不合法的輸入,比如手機號必須是數字,通常可以采用正則表達式 3. 凈化和過濾掉不必要的html標簽,比如:<iframe>, alt,<script> 等 4. 凈化和過濾掉不必要的Javascript的事件標簽,比如:onclick, onfocus等 5. 轉義單引號,雙引號,尖括號等特殊字符,可以采用htmlencode編碼 或者過濾掉這些特殊字符 6. 設置瀏覽器的安全設置來防范典型的XSS注入
2.SQL注入
攻擊方法:
編寫惡意字符串,比如‘ or 1=1--等,
手動測試目標網站上所有涉及數據庫操作的地方
防御方法:
1. 禁止目標網站利用動態拼接字符串的方式訪問數據庫 2. 減少不必要的數據庫拋出的錯誤信息 3. 對數據庫的操作賦予嚴格的權限控制 4. 凈化和過濾掉不必要的SQL保留字,比如:where, or, exec 等 5. 轉義單引號,上引號,尖括號等特殊字符,可以采用htmlencode編碼 或者過濾掉這些特殊字符
3.CSRF,也就是跨站請求偽造
就是攻擊者冒用用戶的名義,向目標站點發送請求
防范方法:
1. 在客戶端進行cookie的hashing,並在服務端進行hash認證 2. 提交請求是需要填寫驗證碼 3. 使用One-Time Tokens為不同的表單創建不同的偽隨機值
40. sessionStorage和localstorage能跨域拿到嗎?比如我在www.baidu.com設置的值能在m.baidu.com能拿到嗎?為什么
localStorage會跟cookie一樣受到跨域的限制,會被document.domain影響
41. localstorage不能手動刪除的時候,什么時候過期
除非被清除,否則永久保存 clear()可清楚
sessionStorage 僅在當前會話下有效,關閉頁面或瀏覽器后被清除
42. cookie可以設置什么域?可以設置.com嗎
可以通過設置domin來實現
43. 登錄狀態的保存你認為可以保存在sessionstorage或者localstorage或者cookie或者你知道的哪種方式,存在了哪里??為什么保存在那里
44. flux -> redux -> mobx 變化的本質是什么
存儲結構 將對象加工可觀察 函數式 vs 面向對象
https://zhuanlan.zhihu.com/p/...
45. 按需加載路由怎么加載對應的chunk文件的?換句話說瀏覽器怎么知道什么時候加載這個chunk,以及webpack是怎么識別那個多個經過hash過的chunk文件
50. get和post有什么區別?get可以通過body傳遞數據嗎
把數據放到 body 里面,必須用 POST 方式取,這是 HTTP 協議限制的。
51. 下拉刷新你怎么實現
52. 預加載options請求為什么會出現,能避免這個請求嗎?
2018年面試題總結
收集一下網上的2018年的面試題 ; 希望能對你有所幫助~~
1.使用css實現一個持續的動畫效果
animation:mymove 5s infinite; @keyframes mymove { from {top:0px;} to {top:200px;} } animation-name 規定需要綁定到選擇器的 keyframe 名稱。 animation-duration 規定完成動畫所花費的時間,以秒或毫秒計。 animation-timing-function 規定動畫的速度曲線。 animation-delay 規定在動畫開始之前的延遲。 animation-iteration-count 規定動畫應該播放的次數。 animation-direction 規定是否應該輪流反向播放動畫。
2.使用js實現一個持續的動畫效果
最開始的思路是用定時器實現,最后沒有想的太完整,面試官給出的答案是用requestAnimationFrame
· 定時器思路
var e = document.getElementById('e') var falg = true; var left = 0; setInterval(() => { left == 0 ? falg = true : left == 100 ? falg = false : '' falg ? e.style.left = ` ${left++}px` : e.style.left = ` ${left--}px` }, 1000 / 60) · requestAnimationFrame 兼容性處理 window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000 / 60); }; })(); var e = document.getElementById("e") var flag = true; var left = 0; function render() { left == 0 ? flag = true : left == 100 ? flag = false : ''; flag ? e.style.left = ` ${left++}px` : e.style.left = ` ${left--}px`; } (function animloop() { render(); requestAnimFrame(animloop); })();
不足之處請指正(畢竟是現學的)順便查了一下優勢:
瀏覽器可以優化並行的動畫動作,更合理的重新排列動作序列,並把能夠合並的動作放在一個渲染周期內完成,從而呈現出更流暢的動畫效果
解決毫秒的不精確性
避免過度渲染(渲染頻率太高、tab 不可見暫停等等)
注:requestAnimFrame 和 定時器一樣也頭一個類似的清除方法 cancelAnimationFrame
3.右邊寬度固定,左邊自適應
第一種:
<style> body{ display: flex; } .left{ background-color: rebeccapurple; height: 200px; flex: 1; } .right{ background-color: red; height: 200px; width: 100px; } </style> <body> <div class="left"></div> <div class="right"></div> </body> 第二種 <style> div { height: 200px; } .left { float: right; width: 200px; background-color: rebeccapurple; } .right { margin-right: 200px; background-color: red; } </style> <body> <div class="left"></div> <div class="right"></div> </body>
4.水平垂直居中
第一種
#container{ position:relative; } #center{ width:100px; height:100px; position:absolute; top:50%; left:50%; transform: translate(-50%,-50%); } 第二種 #container{ position:relative; } #center{ width:100px; height:100px; position:absolute; top:50%; left:50%; margin:-50px 0 0 -50px; } 第三種 #container{ position:relative; } #center{ position:absolute; margin:auto; top:0; bottom:0; left:0; right:0; } 第四種 flex #container{ display:flex; justify-content:center; align-items: center; }
5.四種定位的區別
`static` 是默認值 `relative` 相對定位 相對於自身原有位置進行偏移,仍處於標准文檔流中 `absolute` 絕對定位 相對於最近的已定位的祖先元素, 有已定位(指`position`不是`static`的元素)祖先元素, 以最近的祖先元素為參考標准。如果無已定位祖先元素, 以`body`元素為偏移參照基准, 完全脫離了標准文檔流。 `fixed` 固定定位的元素會相對於視窗來定位,這意味着即便頁面滾動,它還是會停留在相同的位置。一個固定定位元素不會保留它原本在頁面應有的空隙。
6.封裝一個函數,參數是定時器的時間,.then執行回調函數。
function sleep (time) { return new Promise((resolve) => setTimeout(resolve, time)); }
7.一行代碼實現數組去重?
[...new Set([1,2,3,1,'a',1,'a'])]
8.使用addEventListener點擊li彈出內容,並且動態添加li之后有效
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> var ulNode = document.getElementById("ul"); ulNode.addEventListener('click', function (e) { if (e.target && e.target.nodeName.toUpperCase() == "LI") { alert(e.target.innerHTML); } }, false);
9.怎么判斷兩個對象相等
JSON.stringify(obj)==JSON.stringify(obj);//true
10.Vue router 除了 router-link 怎么實現跳轉?
router.go(1) router.push('/')
11.Vue router 跳轉和 location.href 有什么區別?
router
是 hash
改變location.href
是頁面跳轉,刷新頁面
12.重排和重繪
部分渲染樹(或者整個渲染樹)需要重新分析並且節點尺寸需要重新計算。這被稱為重排。注意這里至少會有一次重排-初始化頁面布局。
由於節點的幾何屬性發生改變或者由於樣式發生改變,例如改變元素背景色時,屏幕上的部分內容需要更新。這樣的更新被稱為重繪。
13.什么情況會觸發重排和重繪
添加、刪除、更新 DOM 節點
通過 display: none 隱藏一個 DOM 節點-觸發重排和重繪
通過 visibility: hidden 隱藏一個 DOM 節點-只觸發重繪,因為沒有幾何變化
移動或者給頁面中的 DOM 節點添加動畫
添加一個樣式表,調整樣式屬性
用戶行為,例如調整窗口大小,改變字號,或者滾動。
14.js bind 實現機制?手寫一個 bind 方法?
function bind(fn, context){ return function (){ return fn.apply(context, arguments); } } // 柯理化函數思想 感謝pursuitTom的提出 Function.prototype.bind = function (context) { var args = Array.prototype.slice.call(arguments, 1); var _this = this; return function () { var thisArgs = [].slice.call(arguments); return _this.apply(context, args.concat(thisArgs)) }; } // ES6寫法 感謝waterc的提出 Function.prototype.bind = function(context, ...res) { let self = this return function(...arg) { return self.apply(context, [...res,...arg]) } }
15.多個函數
var a = (function(){return '1';}, function(){return 1;})(); console.log(typeof a); //number
16.__proto__、prototype、Object.getPrototypeOf()
__proto__是指內部原型,和Object.getPrototypeOf()結果等價 function f(){} f.__proto__ === Object.getPrototypeOf(f); //true f.prototype === Object.getPrototypeOf(f); //false
17.瀏覽記錄前后跳轉(尚未試驗)
<a href="javascript:history.go(-1)">backward</a> <a href="javascript:history.go(1)">forward</a>
下面再有的題就不寫序號了;正好到17;是自己喜歡的數字;哈哈
setTimeout 和 setInterval 細談
常問的點,前者是在一定時間過后將函數添加至執行隊列,執行時間=延遲時間+之前函數代碼執行時間+執行函數時間。
后者是不管前一次是否執行完畢,每隔一定時間重復執行,用於精准執行互相沒有影響的重復操作。
如果需要控制前后執行順序,最好使用setTimeout模擬setInterval
var time = 400, times = 0, max = 10; function func(){ times++; if(times < max){ //code here setTimeout(func, time); } else { console.log("finished"); } } setTimeout(func, time);
判斷多圖片加載完畢
注:用jQueryObject.ready()只能判斷dom結構加載完畢
好像描述的不是很清楚,這里寫一下代碼。
方法1:
var counter = 0; var queryInterval = 30; //ms var pics = document.getElementsByClassName("pics"); function singleQuery(i){ if(pics[i].complete){ counter++; console.log(i + " is loaded"); } else { setTimeout(singleQuery, queryInterval, i); } } function allQuery(callback){ if(counter < pics.length){ console.log("current number of loaded pics: " + counter); setTimeout(allQuery, queryInterval, callback); } else { console.log("All pics are loaded."); callback(); } } for(var i = 0; i < pics.length; i++){ setTimeout(singleQuery, queryInterval, i); } setTimeout(allQuery, queryInterval, callback);
主要也是采用setTimeout模擬輪詢,判斷方式是img標簽dom的complete屬性(布爾值),缺點是定時器太多。
方法2:
var counter = 0, queryInterval = 50; var pics = document.getElementsByClassName("pics"); for(var i = 0; i < pics.length; i++){ pics[i].onload = function(){ counter++; console.log(this.id + " is loaded"); } } function queryPictures(callback){ if(counter < pics.length){ console.log("current number of loaded pics: " + counter); setTimeout(queryPictures, queryInterval, callback); } else { console.log("All pics are loaded"); callback(); } } setTimeout(queryPictures, queryInterval, callback);
利用onload綁定圖片加載成功后的回調,通過計數器判斷是否加載完畢。
CSS margin重疊問題
塊元素在垂直方向上的margin是很奇怪的,會有重疊現象。
如果display都是block,有三種情況:
外間距均為正數,豎直方向上會選擇最大的外邊距作為間隔
一正一負,間距 = 正 - |負|
兩個負,間距 = 0 - 絕對值最大的那個
設置display: inline-block的盒子不會有margin重疊,position: absolute的也不會出現。
CSS選擇器優先級 && CSS選擇器效率
ID > 類 > 標簽 > 相鄰 > 子選擇器 > 后代選擇器 > * > 屬性 > 偽類
object.propertyIsEnumerable(xxx)
判斷對象中是否有xxx屬性,並且能通過for in枚舉,如Array對象的length是不可枚舉的
判斷數組
function isArray(arr){ return Object.prototype.toString.call(arr) === '[Object Array]'; }
git fetch && git pull
git pull自動完成了fetch最新遠程版本,並且和本地進行merge
git fetch獲得遠程分支,要繼續手動merge合並
WebSocket
HTML5帶來的新協議,通過類似HTTP的請求建立連接。主要目的是可以獲取服務端的推送。
原來的方式可能是使用long poll(即不中斷連接一直等待數據),或者是ajax輪詢的方式(每隔一段時間發送請求,建立連接,詢問是否有新的數據)。這兩種方式的缺點在於long poll的阻塞,以及ajax輪詢的冗余連接。
WebSocket的設計思想有點類似於回調,在發送請求升級服務端的協議並收到確認信息后,服務端一有新的信息/數據就會主動推送給客戶端,至於要一次HTTP握手便可以建立持久連接
跨域相關
只要協議、域名、端口有不同,則視為不同的域。(域名和域名對應的IP也是跨域)
1.CORS: Cross-Origin Resource Sharing
基於服務器支持的跨域,服務器設置Access-Control-Allow-Origin響應頭,瀏覽器可允許跨域
2.設置domain
能從子域設到主域,如a.b.c.com—>b.c.com—>c.com
具體情況:在頁面中用iframe打開了另一個頁面(前提:兩個頁面主域是相同的)
利用frameElement.contentWindow.document.domain設置frame子頁面的主域,document.domain設置主頁面的主域,之后就能互相獲取dom中的數據。
缺點是只能用於不同子域間的交互。
3.例如擁有src屬性的img標簽,每次改變src屬性,都會發起http請求。
var img = new Image(); img.onload = function(){ //code here }; img.onerror = function(){ //code here }; img.src="http://server.com/data?query=3";
缺點是只能使用GET請求,不能獲取數據,一般用於提交統計信息什么的。
script、link、iframe只有在添加到DOM中才會發起請求
4.HTML5 postMessage
支持IE8+和主流瀏覽器,寫法也簡單..
//source: http://test.org:4000 //get the window object of target origin var win = window.open("http://target.com"); //or this, when a frame is used var win = document.getElementById("targetId").contentWindow; win.postMessage("data here", "http://target.com/rest"); //target: http://target.com/tiny function handleMessage(event){ if(event.orgin!="http://test.org:4000") return; var data = event.data; //code here //event.source is window.opener event.source.postMessage("response data here", event.origin); } window.addEventListener("message", handleMessage, false);
5.window.name
即使在頁面打開多層iframe后,每個iframe中window.name 屬性值都是相同的,以此用作數據傳輸的工具。
但由於跨域的限制,是無法獲取另一個frame中的window.name數據,所以要使用一個同域的代理(proxy.html):
6. jsonp
目前主流跨域方法
調用其他域的腳本獲取數據,前提是另一個域能知道回調函數名,這個可以通過請求發送給目標域。
直接寫jQuery封的jsonp
$.getJSON("http://target.com/data?callback=callbackFunctionName", function(data){});
$.getJSON會把獲取的responseText轉為json,如果url中有callback參數,數據會以script標簽形式獲取。
閉包相關
什么是閉包
閉包是指有權訪問另一個函數作用域中變量的函數
怎么創建閉包
在函數內部嵌套使用函數
function fn() { for (var i = 0; i < 2; i++) { (function () { var variate = i; setTimeout(function () { console.log("setTimeout執行后:"+variate); }, 1000); })();//閉包,立即執行函數,匿名函數 } console.log(i);//2 console.log(variate);//variate is not defined } fn();
為什么用閉包
- 因為在閉包內部保持了對外部活動對象的訪問,但外部的變量卻無法直接訪問內部,避免了全局污染;
- 可以當做私有成員,彌補了因js語法帶來的面向對象編程的不足;
- 可以長久的在內存中保存一個自己想要保存的變量.
閉包的缺點
- 可能導致內存占用過多,因為閉包攜帶了自身的函數作用域
- 閉包只能取得外部包含函數中得最后一個值
詳見https://segmentfault.com/a/11...
a:active 移動端實現
有時候一些按鈕的簡單點擊交互可以通過css偽類來實現;必須點擊了更改顏色;松開恢復;IOS手機會出現偽類無效的情況;iOS系統的移動設備中,需要在按鈕元素或body/html上綁定一個touchstart事件才能激活:active狀態。
document.body.addEventListener('touchstart', function () { //...空函數即可});
ios滑動卡頓
-webkit-overflow-scrolling:touch 可能會在IOS系統低的情況出現滾動條;嘗試溢出解決
forEach和map的區別
相同點
- 都是循環遍歷數組中的每一項
- forEach和map方法里每次執行匿名函數都支持3個參數,參數分別是item(當前每一項)、index(索引值)、arr(原數組)
- 匿名函數中的this都是指向window
- 只能遍歷數組
- 都有兼容問題
不同點
- map速度比foreach快
- map會返回一個新數組,不對原數組產生影響,foreach不會產生新數組,
- map因為返回數組所以可以鏈式操作,foreach不能
淺拷貝和深拷貝
jQuery.extend第一個參數可以是布爾值,用來設置是否深度拷貝的
jQuery.extend(true, { a : { a : "a" } }, { a : { b : "b" } } ); jQuery.extend( { a : { a : "a" } }, { a : { b : "b" } } );
最簡單的深拷貝
aa = JSON.parse( JSON.stringify(a) )
淺復制--->就是將一個對象的內存地址的“”編號“”復制給另一個對象。深復制--->實現原理,先新建一個空對象,內存中新開辟一塊地址,把被復制對象的所有可枚舉的(注意可枚舉的對象)屬性方法一一復制過來,注意要用遞歸來復制子對象里面的所有屬性和方法,直到子子.....屬性為基本數據類型。總結,深復制理解兩點,1,新開辟內存地址,2,遞歸來刨根復制。
外邊距合並
外邊距合並指的是,當兩個垂直外邊距相遇時,它們將形成一個外邊距。
合並后的外邊距的高度等於兩個發生合並的外邊距的高度中的較大者。
Js加載位置區別優缺點
html文件是自上而下的執行方式,但引入的css和javascript的順序有所不同,css引入執行加載時,程序仍然往下執行,而執行到<script>腳本是則中斷線程,待該script腳本執行結束之后程序才繼續往下執行。
所以,大部分網上討論是將script腳本放在<body>之后,那樣dom的生成就不會因為長時間執行script腳本而延遲阻塞,加快了頁面的加載速度。
但又不能將所有的script放在body之后,因為有一些頁面的效果的實現,是需要預先動態的加載一些js腳本。所以這些腳本應該放在<body>之前。
其次,不能將需要訪問dom元素的js放在body之前,因為此時還沒有開始生成dom,所以在body之前的訪問dom元素的js會出錯,或者無效
script放置位置的原則“頁面效果實現類的js應該放在body之前,動作,交互,事件驅動,需要訪問dom屬性的js都可以放在body之后”