摘要:前端示例服務器端代碼可靠的實例添加回調函數拼接傳遞的是一個匿名的回調函數,要執行的話,暴露為一個全局方法出錯處理使用示例歡迎閱讀年前端面試題年前端面試題年前端筆試題我是,年輕的前端攻城獅一枚,愛專研,愛技術,愛分享。
let與var的區別?
Let為ES6新添加申明變量的命令,它類似于var,但是有以下不同:
1、var聲明的變量,其作用域為該語句所在的函數內,且存在變量提升現象
2、let聲明的變量,其作用域為該語句所在的代碼塊內,不存在變量提升
3、let不允許重復聲明.
封裝一個函數,參數是定時器的時間,.then執行回調函數。
function sleep (time) { return new Promise((resolve) => setTimeout(resolve, time)); }
項目做過哪些性能優化?
1、減少HTTP請求數
2、減少DNS查詢
3、使用CDN
4、避免重定向
5、圖片懶加載
6、減少DOM元素數量
7、減少DOM操作
8、使用外部JavaScript和CSS
9、壓縮JavaScript、CSS、字體、圖片等
10、優化CSS Sprite
11、使用iconfont
12、字體裁剪
13、多域名分發劃分內容到不同域名
14、盡量減少iframe使用
15、避免圖片src為空
16、把樣式表放在 中
17、把腳本放在頁面底部
怎么判斷兩個對象相等?
1、轉化成字符串后比較字符串是否一致:
JSON.stringify(obj)===JSON.stringify(obj2);
2、Object.is(obj1,obj2):判斷兩個值是否 [相同]。如果下列任何一項成立,則兩個值相同。
* 兩個值都是 [undefined] * 兩個值都是 [null] * 兩個值都是true或者都是false * 兩個值是由相同個數的字符按照相同的順序組成的字符串 * ~兩個值指向同一個對象~ * 兩個值都是數字并且 * 都是正零+0 * 都是負零-0 * 都是 [NaN] * 都是除零和[NaN]外的其它同一個數字
什么是模塊化開發?
實現mvvm主要包含兩個方面,數據變化更新視圖,視圖變化更新數據:
關鍵點在于data如何更新view,因為view更新data其實可以通過事件監聽即可,比如input標簽監聽 "input" 事件就可以實現了。所以我們著重來分析下,當數據改變,如何更新視圖的。
數據更新視圖的重點是如何知道數據變了,只要知道數據變了,那么接下去的事都好處理。如何知道數據變了,其實上文我們已經給出答案了,就是通過Object.defineProperty( )對屬性設置一個set函數,當數據改變了就會來觸發這個函數,所以我們只要將一些需要更新的方法放在這里面就可以實現data更新view了。
Vue是通過Object.defineProperty()來實現數據劫持的。它可以來控制一個對象屬性的一些特有操作,比如set()、get()、是否可以枚舉。
實現數據的雙向綁定,首先要對數據進行劫持監聽,所以我們需要設置一個監聽器Observer,用來監聽所有屬性。如果屬性發上變化了,就需要告訴訂閱者Watcher看是否需要更新。因為訂閱者是有很多個,所以我們需要有一個消息訂閱器Dep來專門收集這些訂閱者,然后在監聽器Observer和訂閱者Watcher之間進行統一管理的。接著,我們還需要有一個指令解析器Compile,對每個節點元素進行掃描和解析,將相關指令對應初始化成一個訂閱者Watcher,并替換模板數據或者綁定相應的函數,此時當訂閱者Watcher接收到相應屬性的變化,就會執行對應的更新函數,從而更新視圖。因此接下去我們執行以下3個步驟,實現數據的雙向綁定:
1.實現一個監聽器Observer,用來劫持并監聽所有屬性,如果有變動的,就通知訂閱者。
2.實現一個訂閱者Watcher,可以收到屬性的變化通知并執行相應的函數,從而更新視圖。
3.實現一個解析器Compile,可以掃描和解析每個節點的相關指令,并根據初始化模板數據以及初始化相應的訂閱器。
流程圖如下:
瀏覽器兼容性問題
圖片描述
1、Normalize.css
2、不同瀏覽器的標簽默認的外邊距和內邊距不同:
3、IE6雙邊距問題:在 IE6中設置了float , 同時又設置margin , 就會出現邊距問題:設置display:inline;
4、圖片默認有間距:使用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 上不支持:統一使用 cursor:pointer
7、當標簽的高度設置小于10px,在IE6、IE7中會超出自己設置的高度:超出高度的標簽設置overflow:hidden,或者設置line-height的值小于你的設置高度
8、CSS HACK的方法:
height: 100px; // 所有瀏覽器 通用 _height: 100px; // IE6 專用 *+height: 100px; // IE7 專用 *height: 100px; // IE6、IE7 共用 height: 100px !important; // IE7、FF 共用
代碼的順序一定不能顛倒了,要不又前功盡棄了。因為瀏覽器在解釋程序的時候,如果重名的話,會用后面的覆蓋前面的,就象給變量賦值一個道理,所以我們把通用的放前面,越專用的越放后面
前端跨域
什么是跨域?
> 只要協議、域名、端口有任何一個不同,都被當作是不同的域。 > 同源策略是瀏覽器的行為,是為了保護本地數據不被JavaScript代碼獲取回來的數據污染,因此攔截的是客戶端發出的請求回來的數據接收,即請求發送了,服務器響應了,但是無法被瀏覽器接收。 > 之所以會跨域,是因為受到了同源策略的限制,同源策略要求源相同才能正常進行通信,即協議、域名、端口號都完全一致。 > > 注意點: > 如果是協議和端口造成的跨域問題“前臺”是無能為力的; > 在跨域問題上,域僅僅是通過“URL的首部”來識別而不會去嘗試判斷相同的ip地址對應著兩個域或兩個域是否在同一個ip上。 (“URL的首部”指window.location.protocol +window.location.host,也可以理解為“Domains, protocols and ports must match”。)
什么是同源策略?
> 所謂同源是指,域名,協議,端口相同。瀏覽器采用同源策略,就是禁止頁面加載或執行與自身來源不同的域的任何腳本。
通過document.domain跨域(只適用于不同子域的框架間的交互)
瀏覽器有一個同源策略,其限制之一是不能通過ajax的方法去請求不同源中的文檔。第二個限制是瀏覽器中不同域的框架之間是不能進行js的交互操作的。不同的框架之間是可以獲取window對象的,但卻無法獲取相應的屬性和方法。比如,有一個頁面,它的地址是 [www.damonare.cn/a.html], 在這個頁面里面有一個iframe,它的src是 [damonare.cn/b.html], 很顯然,這個頁面與它里面的iframe框架是不同域的,所以我們是無法通過在頁面中書寫js代碼來獲取iframe中的東西的:
通過location.hash跨域
通過HTML5的postMessage方法跨域
通過jsonp跨域
JSONP的優缺點 * JSONP的優點是:它不像XMLHttpRequest對象實現的Ajax請求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中都可以運行,不需要XMLHttpRequest或ActiveX的支持;并且在請求完畢后可以通過調用callback的方式回傳結果。 * JSONP的缺點則是:它只支持GET請求而不支持POST等其它類型的HTTP請求;它只支持跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript調用的問題。
通過CORS跨域
CORS(Cross-Origin Resource Sharing)跨域資源共享,定義了必須在訪問跨域資源時,瀏覽器與服務器應該如何溝通。CORS背后的基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功還是失敗。目前,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10。整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。對于開發者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感覺。
通過window.name跨域
window對象有個name屬性,該屬性有個特征:即在一個窗口(window)的生命周期內,窗口載入的所有的頁面都是共享一個window.name的,每個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗口載入過的所有頁面中的,并不會因新頁面的載入而進行重置。
前端優化:瀏覽器緩存
前端優化:瀏覽器緩存技術介紹 - 掘金
瀏覽器緩存分為強緩存和協商緩存。
當客戶端請求某個資源時,獲取緩存的流程如下:
1)瀏覽器在加載資源時,先根據這個資源的一些http header判斷它是否命中強緩存,強緩存如果命中,瀏覽器直接從自己的緩存中讀取資源,不會發請求到服務器。比如:某個css文件,如果瀏覽器在加載它所在的網頁時,這個css文件的緩存配置命中了強緩存,瀏覽器就直接從緩存中加載這個css,連請求都不會發送到網頁所在服務器;2)當強緩存沒有命中的時候,瀏覽器一定會發送一個請求到服務器,通過服務器端依據資源的另外一些http header驗證這個資源是否命中協商緩存,如果協商緩存命中,服務器會將這個請求返回,但是不會返回這個資源的數據,而是告訴客戶端可以直接從緩存中加載這個資源,于是瀏覽器就又會從自己的緩存中去加載這個資源;
3)強緩存與協商緩存的共同點是:如果命中,都是從客戶端緩存中加載資源,而不是從服務器加載資源數據;區別是:強緩存不發請求到服務器,協商緩存會發請求到服務器。
4)當協商緩存也沒有命中的時候,瀏覽器直接從服務器加載資源數據。
jsonp的原理與實現
Jsonp是一種跨域通信的手段,它的原理其實很簡單:
> 1. 首先是利用script標簽的src屬性來實現跨域。 > 2. 通過將前端方法作為參數傳遞到服務器端,然后由服務器端注入參數之后再返回,實現服務器端向客戶端通信。 > 3. 由于使用script標簽的src屬性,因此只支持get方法
實現流程:
1、設定一個script標簽
2、callback定義了一個函數名,而遠程服務端通過調用指定的函數并傳入參數來實現傳遞參數,將function(response)傳遞回客戶端
$callback = !empty($_GET["callback"]) ? $_GET["callback"] : "callback"; echo $callback."(.json_encode($data).)";
3、客戶端接收到返回的js腳本,開始解析和執行function(response)
簡單的實例:
一個簡單的jsonp實現,其實就是拼接url,然后將動態添加一個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 });
服務器端代碼:
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實例:
(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++; // 添加回調函數 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; // 傳遞的是一個匿名的回調函數,要執行的話,暴露為一個全局方法 global[fnName] = function (ret) { callback && callback(ret); container.removeChild(scriptNode); delete global[fnName]; } // 出錯處理 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,年輕的前端攻城獅一枚,愛專研,愛技術,愛分享。
個人筆記,整理不易,感謝閱讀、點贊和收藏。
文章有任何問題歡迎大家指出,也歡迎大家一起交流前端各種問題!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/114769.html
摘要:前端示例服務器端代碼可靠的實例添加回調函數拼接傳遞的是一個匿名的回調函數,要執行的話,暴露為一個全局方法出錯處理使用示例歡迎閱讀年前端面試題年前端面試題年前端筆試題我是,年輕的前端攻城獅一枚,愛專研,愛技術,愛分享。 let與var的區別? Let為ES6新添加申明變量的命令,它類似于var,但是有以下不同: 1、var聲明的變量,其作用域為該語句所在的函數內,且存在變量提...
摘要:絕對定位的元素不再存在于正常文檔布局流中。則是頁面元素的一個屬性,代表該元素的內容。盡管在中代表但由于的許多優勢,比如更加輕量以及作為的一部分,目前的使用比更加普遍。通配符子選擇器相鄰選擇器等的。值則是表示空對象指針。 ==和===的區別?比較過程: 雙等號==: (1)如果兩個值類型相同,再進行三個等號(===)的比較 ?。?)如果兩個值類型不同,也有可能相...
摘要:絕對定位的元素不再存在于正常文檔布局流中。則是頁面元素的一個屬性,代表該元素的內容。盡管在中代表但由于的許多優勢,比如更加輕量以及作為的一部分,目前的使用比更加普遍。通配符子選擇器相鄰選擇器等的。值則是表示空對象指針。 ==和===的區別?比較過程: 雙等號==: ?。?)如果兩個值類型相同,再進行三個等號(===)的比較 (2)如果兩個值類型不同,也有可能相...
閱讀 1290·2021-11-24 09:39
閱讀 2632·2021-09-30 09:47
閱讀 1325·2021-09-22 15:15
閱讀 2410·2021-09-10 10:51
閱讀 1953·2019-08-30 15:55
閱讀 2977·2019-08-30 11:06
閱讀 896·2019-08-30 10:53
閱讀 830·2019-08-29 17:26