.container {
display: grid;
grid-template-columns: 100px auto 200px;
}
複製代碼
Function.prototype.myBind = function(content) {
if(typeof this !='function'){
throw Error('not a function')
}
let _this = this;
let args = [...arguments].slice(1)
let resFn=function(){
return _this.apply(this instanceof resFn?this:content,args.concat(...arguments))
}
return resFn
};
/** * 每一個函數均可以調用call方法,來改變當前這個函數執行的this關鍵字,而且支持傳入參數 */
Function.prototype.myCall=function(context=window){
context.fn = this;//此處this是指調用myCall的function
let args=[...arguments].slice(1);
let result=content.fn(...args)
//將this指向銷燬
delete context.fn;
return result;
}
/** * apply函數傳入的是this指向和參數數組 */
Function.prototype.myApply = function(context=window) {
context.fn = this;
let result;
if(arguments[1]){
result=context.fn(...arguments[1])
}else{
result=context.fn()
}
//將this指向銷燬
delete context.fn;
return result;
}
複製代碼
[...new Set(arr)]
複製代碼
var arr = [1,2,1,2,3,5,4,5,3,4,4,4,4],
init=[]
var result = arr.sort().reduce((init, current)=>{
console.log(init,current)
if(init.length===0 || init[init.length-1]!==current){
init.push(current);
}
return init;
}, []);
console.log(result);//1,2,3,4,5
複製代碼
var deBounce=function(fn,wait=300){
let timer
return function(){
if(timer){
clearTimeOut(timer)
}
timer=setTimeOut(()=>{
fn.apply(this,arguments)
},wait)
}
}
var throttle = function (fn, wait = 300) {
let prev = +new Date();
return function () {
const args = argument,
now = +new Date();
if (now > prev + wait) {
prev = now;
fn.apply(this, args)
}
}
}
複製代碼
//0 pending,1 resolve,2 reject
function Promise(fn) {...
this._state = 0 // 狀態標記
doResolve(fn, this)
}
function doResolve(fn, self) {
var done = false // 保證只執行一個監聽
try {
fn(function(value) {
if (done) return
done = true
resolve(self, value)
}, function(reason) {
if (done) return;
done = true
reject(self, value)
})
} catch (err) {
if (done) return
done = true
reject(self, err)
}
}
function resolve(self, newValue) {
try {
self._state = 1;
...
} catch (err) {
reject(self, err)
}
}
function reject(self, newValue) {
self._state = 2;
...
if (!self._handled) {
Promise._unhandledRejectionFn(self._value);
}
}
複製代碼
funtion deepCopy(obj){
let result;
if(typeofObj=='object'){
//複雜數據類型
result=obj.constructor==Array?[]:{}
for (let i in obj){
result[i]=typeof obj[i]=='object'?deepCopy(obj[i]):obj[i]
}
}else{
//簡單數據類型
result=obj
}
return result
}
複製代碼
function commafy(num) {
return num && num
.toString()
.replace(/(\d)(?=(\d{3})+\.)/g, function($0, $1) {
return $1 + ",";
});
}
console.log(commafy(1312567.903000))
複製代碼
javascript是單線程語言,任務設計成了兩類,同步任務和異步任務 同步和異步任務分別進入不一樣的執行「場所」,同步進入主線程,異步進入Event Table並註冊函數。當指定的事情完成時,Event Table會將這個函數移入Event Queue。主線程內的任務執行完畢爲空,回去了Event Queue讀取對應的函數,進入主線程。 上述過程會不斷重複,也就是常說的Event Loop(事件循環)。 可是,JS異步還有一個機制,就是遇到宏任務,先執行宏任務,將宏任務放入event queue,而後再執行微任務,將微任務放入eventqueue,可是,這兩個queue不是一個queue。當你往外拿的時候先從微任務裏拿這個回調函數,而後再從宏任務的queue拿宏任務的回調函數 宏任務通常包括:總體代碼script,setTimeout,setInterval。 微任務:Promise,process.nextTickjavascript
事件冒泡和事件捕獲php
事件流分爲:冒泡和捕獲,順序是先捕獲再冒泡。css
事件冒泡:子元素的觸發事件會一直向父節點傳遞,一直到根結點中止。此過程當中,能夠在每一個節點捕捉到相關事件。能夠經過stopPropagation方法終止冒泡。html
事件捕獲:和「事件冒泡」相反,從根節點開始執行,一直向子節點傳遞,直到目標節點。前端
事件捕獲階段 addEventListener給出了第三個參數同時支持冒泡與捕獲:默認是false,事件冒泡;設置爲true時,是事件捕獲。vue
事件委託 事件委託是指將事件綁定目標元素的到父元素上,利用冒泡機制觸發該事件java
event.target返回觸發事件的元素react
event.currentTarget返回綁定事件的元素面試
//方法1
function create(){
//1.建立一個空對象
let obj={}
//2.獲取構造函數
let Con=[].shift.call(arguments)
//3.設置空對象的原型
obj._proto_=Con.prototype
//4.綁定this並執行構造函數,給新對象添加屬性和方法
let result=Con.apply(obj,arguments)
//5.確保返回值爲對象
return result instanceof Object?result:obj
}
//方法2
//經過分析原生的new方法能夠看出,在new一個函數的時候,
// 會返回一個func同時在這個func裏面會返回一個對象Object,
// 這個對象包含父類func的屬性以及隱藏的__proto__
function New(f) {
//返回一個func
return function () {
var o = {"__proto__": f.prototype};
f.apply(o, arguments);//繼承父類的屬性
return o; //返回一個Object
}
}
複製代碼
/* 封裝ajax函數 * @param {string}opt.type http鏈接的方式,包括POST和GET兩種方式 * @param {string}opt.url 發送請求的url * @param {boolean}opt.async 是否爲異步請求,true爲異步的,false爲同步的 * @param {object}opt.data 發送的參數,格式爲對象類型 * @param {function}opt.success ajax發送並接收成功調用的回調函數 */
function myAjax(opt){
opt = opt || {};
opt.method = opt.method.toUpperCase() || 'POST';
opt.url = opt.url || '';
opt.async = opt.async || true;
opt.data = opt.data || null;
opt.success = opt.success || function () {}
let xmlHttp = null;
if (XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}else{
xmlHttp =new ActiveXObject('Microsoft.XMLHTTP')
}
let params;
for (var key in opt.data){
params.push(key + '=' + opt.data[key]);
}
let postData = params.join('&');
if (opt.method.toUpperCase() === 'POST') {
xmlHttp.open(opt.method, opt.url, opt.async);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
xmlHttp.send(postData);
}else if (opt.method.toUpperCase() === 'GET') {
xmlHttp.open(opt.method, opt.url + '?' + postData, opt.async);
xmlHttp.send(null);
}
xmlHttp.onreadystatechange= function () {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
opt.success(xmlHttp.responseText);//若是是json數據能夠在這使用opt.success(JSON.parse( xmlHttp.responseText))
}
};
}
複製代碼
var url = "http://www.taobao.com/index.php?key0=0&key1=1&key2=2";
function parseQueryString(url){
var str = url.split("?")[1], //經過?獲得一個數組,取?後面的參數
items = str.split("&"); //分割成數組
var arr,name,value;
for(var i=0; i<items.length; i++){
arr = items[i].split("="); //["key0", "0"]
name = arr[0];
value = arr[1];
this[name] = value;
}
}
var obj = new parseQueryString(url);
alert(obj.key2)
複製代碼
HTTP協議(超文本傳輸協議)ajax
1.1 改進:
HTTP之請求消息Request
HTTP之響應消息Response
HTTP響應也由四個部分組成,分別是:狀態行、消息報頭、空行和響應正文。
SYN (同步序列編號)ACK(確認字符)
這是由於服務端在LISTEN狀態下,收到創建鏈接請求的SYN報文後,把ACK和SYN放在一個報文裏發送給客戶端。而關閉鏈接時,當收到對方的FIN報文時,僅僅表示對方再也不發送數據了可是還能接收數據,己方也未必所有數據都發送給對方了,因此己方能夠當即close,也能夠發送一些數據給對方後,再發送FIN報文給對方來表示贊成如今關閉鏈接,所以,己方ACK和FIN通常都會分開發送。
非對稱加密與對稱加密雙劍合璧,使用非對稱加密算法傳遞用於對稱加密算法的密鑰,而後使用對稱加密算法進行信息傳遞。這樣既安全又高效
當瀏覽器再次訪問一個已經訪問過的資源時,它會這樣作:
其實 VNode 是對真實 DOM 的一種抽象描述,它的核心定義無非就幾個關鍵屬性,標籤名、數據、子節點、鍵值等,其它屬性都是都是用來擴展 VNode 的靈活性以及實現一些特殊 feature 的。因爲 VNode 只是用來映射到真實 DOM 的渲染,不須要包含操做 DOM 的方法,所以它是很是輕量和簡單的。 Virtual DOM 除了它的數據結構的定義,映射到真實的 DOM 實際上要經歷 VNode 的 create(用JS對象模擬DOM樹)、diff(比較兩棵虛擬DOM樹的差別)、patch(把差別應用到真正的DOM樹上) 等過程。
對樹進行分層比較,兩棵樹只會對同一層次的節點進行比較。(由於 DOM 節點跨層級的移動操做少到能夠忽略不計) 若是父節點已經不存在,則該節點及其子節點會被徹底刪除掉,不會用於進一步的比較。 注意: React 官方建議不要進行 DOM 節點跨層級的操做,很是影響 React 性能。 在開發組件時,保持穩定的 DOM 結構會有助於性能的提高。例如,能夠經過 CSS 隱藏或顯示節點,而不是真的移除或添加 DOM 節點。
若是是同一類型的組件,按照原策略繼續比較 virtual DOM tree(tree diff)。 對於同一類型的組件,有可能其 Virtual DOM 沒有任何變化,若是可以確切的知道這點那能夠節省大量的 diff 運算時間,所以 React 容許用戶經過 shouldComponentUpdate() 來判斷該組件是否須要進行 diff。 若是不是,直接替換整個組件下的全部子節點。
對處於同一層級的節點進行對比。 這時 React 建議:添加惟一 key 進行區分。雖然只是小小的改動,性能上卻發生了翻天覆地的變化! 如: A B C D --> B A D C 添加 key 以前: 發現 B != A,則建立並插入 B 至新集合,刪除老集合 A;以此類推,建立並插入 A、D 和 C,刪除 B、C 和 D。 添加 key 以後: B、D 不作任何操做,A、C 進行移動操做,便可。 建議:在開發過程當中,儘可能減小相似將最後一個節點移動到列表首部的操做,當節點數量過大或更新操做過於頻繁時,在必定程度上會影響 React 的渲染性能。
Object.defineProperty(obj, prop, descriptor)
observe
// 解析模板字符串生成 AST
const ast = parse(template.trim(), options)
//優化語法樹
optimize(ast, options)
//生成代碼
const code = generate(ast, options)
複製代碼
vuex
預防:
使用XSS Filter
<script>
中,能夠進行JS編碼。使用 HttpOnly Cookie 將重要的cookie標記爲httponly,這樣的話當瀏覽器向Web服務器發起請求的時就會帶上cookie字段,可是在js腳本中卻不能訪問這個cookie,這樣就避免了XSS攻擊利用JavaScript的document.cookie獲取cookie。
CSRF:跨站請求僞造,也稱 XSRF,是一種挾制用戶在當前已登陸的Web應用程序上執行非本意的操做的攻擊方法。與 XSS 相比,XSS利用的是用戶對指定網站的信任,CSRF利用的是網站對用戶網頁瀏覽器的信任。