摘要:前端示例服務(wù)器端代碼可靠的實(shí)例添加回調(diào)函數(shù)拼接傳遞的是一個(gè)匿名的回調(diào)函數(shù),要執(zhí)行的話,暴露為一個(gè)全局方法出錯(cuò)處理使用示例歡迎閱讀年前端面試題年前端面試題年前端筆試題我是,年輕的前端攻城獅一枚,愛專研,愛技術(shù),愛分享。
let與var的區(qū)別?
Let為ES6新添加申明變量的命令,它類似于var,但是有以下不同:
1、var聲明的變量,其作用域?yàn)樵撜Z句所在的函數(shù)內(nèi),且存在變量提升現(xiàn)象
2、let聲明的變量,其作用域?yàn)樵撜Z句所在的代碼塊內(nèi),不存在變量提升
3、let不允許重復(fù)聲明.
封裝一個(gè)函數(shù),參數(shù)是定時(shí)器的時(shí)間,.then執(zhí)行回調(diào)函數(shù)。
function sleep (time) { return new Promise((resolve) => setTimeout(resolve, time)); }
項(xiàng)目做過哪些性能優(yōu)化?
1、減少HTTP請(qǐng)求數(shù)
2、減少DNS查詢
3、使用CDN
4、避免重定向
5、圖片懶加載
6、減少DOM元素?cái)?shù)量
7、減少DOM操作
8、使用外部JavaScript和CSS
9、壓縮JavaScript、CSS、字體、圖片等
10、優(yōu)化CSS Sprite
11、使用iconfont
12、字體裁剪
13、多域名分發(fā)劃分內(nèi)容到不同域名
14、盡量減少iframe使用
15、避免圖片src為空
16、把樣式表放在 中
17、把腳本放在頁面底部
怎么判斷兩個(gè)對(duì)象相等?
1、轉(zhuǎn)化成字符串后比較字符串是否一致:
JSON.stringify(obj)===JSON.stringify(obj2);
2、Object.is(obj1,obj2):判斷兩個(gè)值是否 [相同]。如果下列任何一項(xiàng)成立,則兩個(gè)值相同。
* 兩個(gè)值都是 [undefined] * 兩個(gè)值都是 [null] * 兩個(gè)值都是true或者都是false * 兩個(gè)值是由相同個(gè)數(shù)的字符按照相同的順序組成的字符串 * ~兩個(gè)值指向同一個(gè)對(duì)象~ * 兩個(gè)值都是數(shù)字并且 * 都是正零+0 * 都是負(fù)零-0 * 都是 [NaN] * 都是除零和[NaN]外的其它同一個(gè)數(shù)字
什么是模塊化開發(fā)?
實(shí)現(xiàn)mvvm主要包含兩個(gè)方面,數(shù)據(jù)變化更新視圖,視圖變化更新數(shù)據(jù):
關(guān)鍵點(diǎn)在于data如何更新view,因?yàn)関iew更新data其實(shí)可以通過事件監(jiān)聽即可,比如input標(biāo)簽監(jiān)聽 "input" 事件就可以實(shí)現(xiàn)了。所以我們著重來分析下,當(dāng)數(shù)據(jù)改變,如何更新視圖的。
數(shù)據(jù)更新視圖的重點(diǎn)是如何知道數(shù)據(jù)變了,只要知道數(shù)據(jù)變了,那么接下去的事都好處理。如何知道數(shù)據(jù)變了,其實(shí)上文我們已經(jīng)給出答案了,就是通過Object.defineProperty( )對(duì)屬性設(shè)置一個(gè)set函數(shù),當(dāng)數(shù)據(jù)改變了就會(huì)來觸發(fā)這個(gè)函數(shù),所以我們只要將一些需要更新的方法放在這里面就可以實(shí)現(xiàn)data更新view了。
Vue是通過Object.defineProperty()來實(shí)現(xiàn)數(shù)據(jù)劫持的。它可以來控制一個(gè)對(duì)象屬性的一些特有操作,比如set()、get()、是否可以枚舉。
實(shí)現(xiàn)數(shù)據(jù)的雙向綁定,首先要對(duì)數(shù)據(jù)進(jìn)行劫持監(jiān)聽,所以我們需要設(shè)置一個(gè)監(jiān)聽器Observer,用來監(jiān)聽所有屬性。如果屬性發(fā)上變化了,就需要告訴訂閱者Watcher看是否需要更新。因?yàn)橛嗛喺呤怯泻芏鄠€(gè),所以我們需要有一個(gè)消息訂閱器Dep來專門收集這些訂閱者,然后在監(jiān)聽器Observer和訂閱者Watcher之間進(jìn)行統(tǒng)一管理的。接著,我們還需要有一個(gè)指令解析器Compile,對(duì)每個(gè)節(jié)點(diǎn)元素進(jìn)行掃描和解析,將相關(guān)指令對(duì)應(yīng)初始化成一個(gè)訂閱者Watcher,并替換模板數(shù)據(jù)或者綁定相應(yīng)的函數(shù),此時(shí)當(dāng)訂閱者Watcher接收到相應(yīng)屬性的變化,就會(huì)執(zhí)行對(duì)應(yīng)的更新函數(shù),從而更新視圖。因此接下去我們執(zhí)行以下3個(gè)步驟,實(shí)現(xiàn)數(shù)據(jù)的雙向綁定:
1.實(shí)現(xiàn)一個(gè)監(jiān)聽器Observer,用來劫持并監(jiān)聽所有屬性,如果有變動(dòng)的,就通知訂閱者。
2.實(shí)現(xiàn)一個(gè)訂閱者Watcher,可以收到屬性的變化通知并執(zhí)行相應(yīng)的函數(shù),從而更新視圖。
3.實(shí)現(xiàn)一個(gè)解析器Compile,可以掃描和解析每個(gè)節(jié)點(diǎn)的相關(guān)指令,并根據(jù)初始化模板數(shù)據(jù)以及初始化相應(yīng)的訂閱器。
流程圖如下:
瀏覽器兼容性問題
圖片描述
1、Normalize.css
2、不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外邊距和內(nèi)邊距不同:
3、IE6雙邊距問題:在 IE6中設(shè)置了float , 同時(shí)又設(shè)置margin , 就會(huì)出現(xiàn)邊距問題:設(shè)置display:inline;
4、圖片默認(rèn)有間距:使用float 為img 布局
5、IE9以下瀏覽器不能使用opacity:
opacity: 0.5; filter: alpha(opacity = 50); filter: progid:DXImageTransform.Microsoft.Alpha(style = 0, opacity = 50);
6、cursor:hand 顯示手型在safari 上不支持:統(tǒng)一使用 cursor:pointer
7、當(dāng)標(biāo)簽的高度設(shè)置小于10px,在IE6、IE7中會(huì)超出自己設(shè)置的高度:超出高度的標(biāo)簽設(shè)置overflow:hidden,或者設(shè)置line-height的值小于你的設(shè)置高度
8、CSS HACK的方法:
height: 100px; // 所有瀏覽器 通用 _height: 100px; // IE6 專用 *+height: 100px; // IE7 專用 *height: 100px; // IE6、IE7 共用 height: 100px !important; // IE7、FF 共用
代碼的順序一定不能顛倒了,要不又前功盡棄了。因?yàn)闉g覽器在解釋程序的時(shí)候,如果重名的話,會(huì)用后面的覆蓋前面的,就象給變量賦值一個(gè)道理,所以我們把通用的放前面,越專用的越放后面
前端跨域
什么是跨域?
> 只要協(xié)議、域名、端口有任何一個(gè)不同,都被當(dāng)作是不同的域。 > 同源策略是瀏覽器的行為,是為了保護(hù)本地?cái)?shù)據(jù)不被JavaScript代碼獲取回來的數(shù)據(jù)污染,因此攔截的是客戶端發(fā)出的請(qǐng)求回來的數(shù)據(jù)接收,即請(qǐng)求發(fā)送了,服務(wù)器響應(yīng)了,但是無法被瀏覽器接收。 > 之所以會(huì)跨域,是因?yàn)槭艿搅送床呗缘南拗疲床呗砸笤聪嗤拍苷_M(jìn)行通信,即協(xié)議、域名、端口號(hào)都完全一致。 > > 注意點(diǎn): > 如果是協(xié)議和端口造成的跨域問題“前臺(tái)”是無能為力的; > 在跨域問題上,域僅僅是通過“URL的首部”來識(shí)別而不會(huì)去嘗試判斷相同的ip地址對(duì)應(yīng)著兩個(gè)域或兩個(gè)域是否在同一個(gè)ip上。 (“URL的首部”指window.location.protocol +window.location.host,也可以理解為“Domains, protocols and ports must match”。)
什么是同源策略?
> 所謂同源是指,域名,協(xié)議,端口相同。瀏覽器采用同源策略,就是禁止頁面加載或執(zhí)行與自身來源不同的域的任何腳本。
通過document.domain跨域(只適用于不同子域的框架間的交互)
瀏覽器有一個(gè)同源策略,其限制之一是不能通過ajax的方法去請(qǐng)求不同源中的文檔。第二個(gè)限制是瀏覽器中不同域的框架之間是不能進(jìn)行js的交互操作的。不同的框架之間是可以獲取window對(duì)象的,但卻無法獲取相應(yīng)的屬性和方法。比如,有一個(gè)頁面,它的地址是 [www.damonare.cn/a.html], 在這個(gè)頁面里面有一個(gè)iframe,它的src是 [damonare.cn/b.html], 很顯然,這個(gè)頁面與它里面的iframe框架是不同域的,所以我們是無法通過在頁面中書寫js代碼來獲取iframe中的東西的:
通過location.hash跨域
通過HTML5的postMessage方法跨域
通過jsonp跨域
JSONP的優(yōu)缺點(diǎn) * JSONP的優(yōu)點(diǎn)是:它不像XMLHttpRequest對(duì)象實(shí)現(xiàn)的Ajax請(qǐng)求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中都可以運(yùn)行,不需要XMLHttpRequest或ActiveX的支持;并且在請(qǐng)求完畢后可以通過調(diào)用callback的方式回傳結(jié)果。 * JSONP的缺點(diǎn)則是:它只支持GET請(qǐng)求而不支持POST等其它類型的HTTP請(qǐng)求;它只支持跨域HTTP請(qǐng)求這種情況,不能解決不同域的兩個(gè)頁面之間如何進(jìn)行JavaScript調(diào)用的問題。
通過CORS跨域
CORS(Cross-Origin Resource Sharing)跨域資源共享,定義了必須在訪問跨域資源時(shí),瀏覽器與服務(wù)器應(yīng)該如何溝通。CORS背后的基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務(wù)器進(jìn)行溝通,從而決定請(qǐng)求或響應(yīng)是應(yīng)該成功還是失敗。目前,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10。整個(gè)CORS通信過程,都是瀏覽器自動(dòng)完成,不需要用戶參與。對(duì)于開發(fā)者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發(fā)現(xiàn)AJAX請(qǐng)求跨源,就會(huì)自動(dòng)添加一些附加的頭信息,有時(shí)還會(huì)多出一次附加的請(qǐng)求,但用戶不會(huì)有感覺。
通過window.name跨域
window對(duì)象有個(gè)name屬性,該屬性有個(gè)特征:即在一個(gè)窗口(window)的生命周期內(nèi),窗口載入的所有的頁面都是共享一個(gè)window.name的,每個(gè)頁面對(duì)window.name都有讀寫的權(quán)限,window.name是持久存在一個(gè)窗口載入過的所有頁面中的,并不會(huì)因新頁面的載入而進(jìn)行重置。
前端優(yōu)化:瀏覽器緩存
前端優(yōu)化:瀏覽器緩存技術(shù)介紹 - 掘金
瀏覽器緩存分為強(qiáng)緩存和協(xié)商緩存。
當(dāng)客戶端請(qǐng)求某個(gè)資源時(shí),獲取緩存的流程如下:
1)瀏覽器在加載資源時(shí),先根據(jù)這個(gè)資源的一些http header判斷它是否命中強(qiáng)緩存,強(qiáng)緩存如果命中,瀏覽器直接從自己的緩存中讀取資源,不會(huì)發(fā)請(qǐng)求到服務(wù)器。比如:某個(gè)css文件,如果瀏覽器在加載它所在的網(wǎng)頁時(shí),這個(gè)css文件的緩存配置命中了強(qiáng)緩存,瀏覽器就直接從緩存中加載這個(gè)css,連請(qǐng)求都不會(huì)發(fā)送到網(wǎng)頁所在服務(wù)器;2)當(dāng)強(qiáng)緩存沒有命中的時(shí)候,瀏覽器一定會(huì)發(fā)送一個(gè)請(qǐng)求到服務(wù)器,通過服務(wù)器端依據(jù)資源的另外一些http header驗(yàn)證這個(gè)資源是否命中協(xié)商緩存,如果協(xié)商緩存命中,服務(wù)器會(huì)將這個(gè)請(qǐng)求返回,但是不會(huì)返回這個(gè)資源的數(shù)據(jù),而是告訴客戶端可以直接從緩存中加載這個(gè)資源,于是瀏覽器就又會(huì)從自己的緩存中去加載這個(gè)資源;
3)強(qiáng)緩存與協(xié)商緩存的共同點(diǎn)是:如果命中,都是從客戶端緩存中加載資源,而不是從服務(wù)器加載資源數(shù)據(jù);區(qū)別是:強(qiáng)緩存不發(fā)請(qǐng)求到服務(wù)器,協(xié)商緩存會(huì)發(fā)請(qǐng)求到服務(wù)器。
4)當(dāng)協(xié)商緩存也沒有命中的時(shí)候,瀏覽器直接從服務(wù)器加載資源數(shù)據(jù)。
jsonp的原理與實(shí)現(xiàn)
Jsonp是一種跨域通信的手段,它的原理其實(shí)很簡(jiǎn)單:
> 1. 首先是利用script標(biāo)簽的src屬性來實(shí)現(xiàn)跨域。 > 2. 通過將前端方法作為參數(shù)傳遞到服務(wù)器端,然后由服務(wù)器端注入?yún)?shù)之后再返回,實(shí)現(xiàn)服務(wù)器端向客戶端通信。 > 3. 由于使用script標(biāo)簽的src屬性,因此只支持get方法
實(shí)現(xiàn)流程:
1、設(shè)定一個(gè)script標(biāo)簽
2、callback定義了一個(gè)函數(shù)名,而遠(yuǎn)程服務(wù)端通過調(diào)用指定的函數(shù)并傳入?yún)?shù)來實(shí)現(xiàn)傳遞參數(shù),將function(response)傳遞回客戶端
$callback = !empty($_GET["callback"]) ? $_GET["callback"] : "callback"; echo $callback."(.json_encode($data).)";
3、客戶端接收到返回的js腳本,開始解析和執(zhí)行function(response)
簡(jiǎn)單的實(shí)例:
一個(gè)簡(jiǎn)單的jsonp實(shí)現(xiàn),其實(shí)就是拼接url,然后將動(dòng)態(tài)添加一個(gè)script元素到頭部。
function jsonp(req){ var script = document.createElement("script"); var url = req.url + "?callback=" + req.callback.name; script.src = url; document.getElementsByTagName("head")[0].appendChild(script); }
前端js示例:
function hello(res){ alert("hello " + res.data); } jsonp({ url : "", callback : hello });
服務(wù)器端代碼:
var http = require("http"); var urllib = require("url"); var port = 8080; var data = {"data":"world"}; http.createServer(function(req,res){ var params = urllib.parse(req.url,true); if(params.query.callback){ console.log(params.query.callback); //jsonp var str = params.query.callback + "(" + JSON.stringify(data) + ")"; res.end(str); } else { res.end(); } }).listen(port,function(){ console.log("jsonp server is on"); });
可靠的jsonp實(shí)例:
(function (global) { var id = 0, container = document.getElementsByTagName("head")[0]; function jsonp(options) { if(!options || !options.url) return; var scriptNode = document.createElement("script"), data = options.data || {}, url = options.url, callback = options.callback, fnName = "jsonp" + id++; // 添加回調(diào)函數(shù) data["callback"] = fnName; // 拼接url var params = []; for (var key in data) { params.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key])); } url = url.indexOf("?") > 0 ? (url + "&") : (url + "?"); url += params.join("&"); scriptNode.src = url; // 傳遞的是一個(gè)匿名的回調(diào)函數(shù),要執(zhí)行的話,暴露為一個(gè)全局方法 global[fnName] = function (ret) { callback && callback(ret); container.removeChild(scriptNode); delete global[fnName]; } // 出錯(cuò)處理 scriptNode.onerror = function () { callback && callback({error:"error"}); container.removeChild(scriptNode); global[fnName] && delete global[fnName]; } scriptNode.type = "text/javascript"; container.appendChild(scriptNode) } global.jsonp = jsonp; })(this);
使用示例:
jsonp({ url : "www.example.com", data : {id : 1}, callback : function (ret) { console.log(ret); } });
歡迎閱讀:
2019年前端面試題-01
2019年前端面試題-02
2019年前端筆試題
我是Cloudy,年輕的前端攻城獅一枚,愛專研,愛技術(shù),愛分享。
個(gè)人筆記,整理不易,感謝閱讀、點(diǎn)贊和收藏。
文章有任何問題歡迎大家指出,也歡迎大家一起交流前端各種問題!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/104504.html
摘要:前端示例服務(wù)器端代碼可靠的實(shí)例添加回調(diào)函數(shù)拼接傳遞的是一個(gè)匿名的回調(diào)函數(shù),要執(zhí)行的話,暴露為一個(gè)全局方法出錯(cuò)處理使用示例歡迎閱讀年前端面試題年前端面試題年前端筆試題我是,年輕的前端攻城獅一枚,愛專研,愛技術(shù),愛分享。 let與var的區(qū)別? Let為ES6新添加申明變量的命令,它類似于var,但是有以下不同: 1、var聲明的變量,其作用域?yàn)樵撜Z句所在的函數(shù)內(nèi),且存在變量提...
摘要:絕對(duì)定位的元素不再存在于正常文檔布局流中。則是頁面元素的一個(gè)屬性,代表該元素的內(nèi)容。盡管在中代表但由于的許多優(yōu)勢(shì),比如更加輕量以及作為的一部分,目前的使用比更加普遍。通配符子選擇器相鄰選擇器等的。值則是表示空對(duì)象指針。 ==和===的區(qū)別?比較過程: 雙等號(hào)==: (1)如果兩個(gè)值類型相同,再進(jìn)行三個(gè)等號(hào)(===)的比較 (2)如果兩個(gè)值類型不同,也有可能相...
摘要:絕對(duì)定位的元素不再存在于正常文檔布局流中。則是頁面元素的一個(gè)屬性,代表該元素的內(nèi)容。盡管在中代表但由于的許多優(yōu)勢(shì),比如更加輕量以及作為的一部分,目前的使用比更加普遍。通配符子選擇器相鄰選擇器等的。值則是表示空對(duì)象指針。 ==和===的區(qū)別?比較過程: 雙等號(hào)==: (1)如果兩個(gè)值類型相同,再進(jìn)行三個(gè)等號(hào)(===)的比較 (2)如果兩個(gè)值類型不同,也有可能相...
閱讀 2526·2021-09-24 10:29
閱讀 3806·2021-09-22 15:46
閱讀 2575·2021-09-04 16:41
閱讀 2982·2019-08-30 15:53
閱讀 1263·2019-08-30 14:24
閱讀 3057·2019-08-30 13:19
閱讀 2172·2019-08-29 14:17
閱讀 3525·2019-08-29 12:55