css
清浮動(dòng)影響
1.父元素添加overflow:hidden。
overflow:hidden作用機(jī)制BFC:BFC(Block Formatting Context)全稱是塊級(jí)格式化上下文,用于對(duì)塊級(jí)元素排版,默認(rèn)情況下只有根元素(body)一個(gè)塊級(jí)上下文,但是如果一個(gè)塊級(jí)元素設(shè)置了float:left,overflow:hidden或position:absolute樣式,就會(huì)為這個(gè)塊級(jí)元素生產(chǎn)一個(gè)獨(dú)立的塊級(jí)上下文,使這個(gè)塊級(jí)元素內(nèi)部的排版完全獨(dú)立。
獨(dú)立的塊級(jí)上下文可以包裹浮動(dòng)流,全部浮動(dòng)子元素也不會(huì)引起容器高度塌陷,就是說包含塊會(huì)把浮動(dòng)元素的高度也計(jì)算在內(nèi),所以就不用清除浮動(dòng)來撐起包含塊的高度。
那什么時(shí)候會(huì)觸發(fā) BFC 呢?常見的情況如下:
<html>根元素;
float的值不為none;
overflow的值為auto、scroll或hidden;
display的值為table-cell、table-caption和inline-block中的任何一個(gè);
position的值不為relative和static。
2.使用clear屬性。使用偽類 :after
:after:{
content: '';
height: 0;
line-height: 0;
display: block;
visibility: hidden;
clear: both;
}
- 末尾添加額外標(biāo)簽設(shè)置
clear:both;與上同原理 - 設(shè)置父元素為浮動(dòng)元素
- 設(shè)置父元素position:absolute
css實(shí)現(xiàn)吸頂效果方式
flex布局
實(shí)現(xiàn)吸頂效果方式 詳細(xì)查看
1.css
2.js:
-獲取元素距離頂部距離(offsetTop)與滾動(dòng)條滾動(dòng)距離(scrollTop),后者>前者 就修改pisition為fix
-使用 el.getBoundingClientRect().top 實(shí)現(xiàn),此方法獲取元素距離視窗的頂部距離,小于0就修改pisition為fix
優(yōu)化:
-吸頂?shù)哪且豢贪殡S抖動(dòng),在吸頂元素 position 變?yōu)?fixed 的時(shí)候,該元素就脫離了文檔流,下一個(gè)元素就進(jìn)行了補(bǔ)位。就是這個(gè)補(bǔ)位操作造成了抖動(dòng)。
解決方案:為這個(gè)吸頂元素添加一個(gè)等高的父元素,我們監(jiān)聽這個(gè)父元素的值來實(shí)現(xiàn)吸頂效果
-吸頂效果不能及時(shí)響應(yīng),在 ios 系統(tǒng)上不能實(shí)時(shí)監(jiān)聽 scroll 滾動(dòng)監(jiān)聽事件,在滾動(dòng)停止時(shí)才觸發(fā)其相關(guān)的事件。
解決方案:IOS 使用 position:sticky,Android 使用滾動(dòng)監(jiān)聽 getBoundingClientRect().top 的值。
-頻繁獲取滾動(dòng)元素信息,引起reflow
解決方案:1、犧牲平滑度滿足性能,使用節(jié)流控制相關(guān)方法的調(diào)用;2、使用 IntersectionObserver 和節(jié)流結(jié)合,也犧牲了平滑度。
IntersectionObserverFun: function() { let self = this; let ele = self.$refs.pride_tab_fixed; if( !IntersectionObserver ){ let observer = new IntersectionObserver(function(){ let offsetTop = ele.getBoundingClientRect().top; self.titleFixed = offsetTop < 0; }, { threshold: [1] }); observer.observe(document.getElementsByClassName('title_box')[0]); } else { window.addEventListener('scroll', _.throttle(function(){ let offsetTop = ele.getBoundingClientRect().top; self.titleFixed = offsetTop < 0; }, 50)); } },
js
數(shù)據(jù)類型
- 基本類型:Symbol、Number、Undefined、null、String、Boolean
- 引用類型:Function、Object、Array
數(shù)組方法
- slice(int start,int end): Array
- splice(int start,int number, ...newItem): Array deleted 從start開始刪除 number個(gè)元素,并添加 newItem。返回刪除的元素?cái)?shù)組,影響原數(shù)組
- join(separator):String 對(duì)于非字符串會(huì)調(diào)用其toString方法
- push(...items):int 末尾添加,返回?cái)?shù)組長(zhǎng)度,會(huì)改變?cè)瓟?shù)組
- pop():any|undefined 刪除末尾元素,返回被刪除的元素,會(huì)改變?cè)瓟?shù)組
- shift():any|undefined 刪除首位元素,返回被刪除的元素,會(huì)改變?cè)瓟?shù)組
- unshift(...items):int 開頭添加,返回?cái)?shù)組長(zhǎng)度,會(huì)改變?cè)瓟?shù)組
- sort((item:any, item1:any)=>:int):Array 返回值小于0正序,大于0倒序,影響原數(shù)組
- reverse():Array 反轉(zhuǎn)數(shù)據(jù),改變?cè)瓟?shù)組
- forEach(item:ant=>:int):undefined 不改變?cè)磾?shù)組
- filter(item:any=>:boolean):Array 不改變?cè)磾?shù)組,返回新數(shù)組
- reduce((total:any, currentValue:any, currentIndex:int, arr:Array)=>total:any, initialValue:any) 累加器,最終返回total,注意函數(shù)一定要return
- reduceRight 同上,只是遍歷從后忘前
- indexOf(target:any):int 查找目標(biāo)元素在數(shù)組中首次出現(xiàn)的下標(biāo),未找到返回-1
- lastIndexOf(target:any):int 查找目標(biāo)元素在數(shù)組中最后一次出現(xiàn)的下標(biāo),未找到返回-1
- includes(target:any):Boolean 查找目標(biāo)元素是否存在數(shù)組中
- find((item:any, index:int, arr:Array)=>:Boolean, thisValue:any):any|undefined 找到后不再執(zhí)行其他元素
- findIndex((item:any, index:int, arr:Array)=>:Boolean, thisValue:any):int 找到后不再執(zhí)行其他元素
- every((item:any, index:int, arr:Array)=>:Boolean, thisValue:any):Boolean 判斷是否都返回true
- some((item:any, index:int, arr:Array)=>:Boolean, thisValue:any):Boolean 判斷是否至少一個(gè)返回true
- fill(value:any, start=0:int, end=length:int):Array 填充元素,改變?cè)瓟?shù)組
- keys():Array Iterator entries():Array Iterator 迭代器
字符串方法
- split(separator:any):Array 返回separator分割后形成的數(shù)組
- concat(...item:any):String 連接字符串,返回新的字符串
- substr(start=0:int, number=length:int):String 從start位置提取number個(gè)字符
- substring(start=0:int, stop=length:int):String 從start位置提取到stop之間的字符,不允許使用負(fù)數(shù)
- slice(start=0:int, stop=length:int):String 從start位置提取到stop之間的字符,允許使用負(fù)數(shù)
- replace(reg:RegExp|String, target:any):String 返回新字符串
- toUpperCase():String 返回新字符串
- toLowerCase():String 返回新字符串
- startsWith(target:any):Boolean
- endsWith(target:any):Boolean
- includes(target:any):Boolean
- indexOf(target:any):int 查找目標(biāo)元素在首次出現(xiàn)的下標(biāo),未找到返回-1
- lastIndexOf(target:any):int 查找目標(biāo)元素在最后一次出現(xiàn)的下標(biāo),未找到返回-1
- search(target:RegExp|String):int 匹配目標(biāo)元素在首次出現(xiàn)的下標(biāo),未找到返回-1
- padStart(len:int, target:any):String 返回新字符串,在前面使用target補(bǔ)齊達(dá)到len長(zhǎng)度
- padEnd(len:int, target:any):String 返回新字符串,在后面使用target補(bǔ)齊達(dá)到len長(zhǎng)度
- match(reg:RegExp|String):null|Array 返回匹配情況
- matchAll(reg:RegExp|String):RegExp String Iterator 返回迭代器,注意reg不帶g(全局匹配)回拋出異常
- charAt(int):String 返回指定下標(biāo)的字符
- trim() 返回新字符串
- trimStart(別名:trimLeft) trimEnd (別名:trimRight) 返回新字符串
判斷類型:Object.prototype.toString,可準(zhǔn)確判斷出具體類型
ES6新語法、屬性、方法
Object.create() 方法創(chuàng)建一個(gè)新對(duì)象,使用現(xiàn)有的對(duì)象來提供新創(chuàng)建的對(duì)象的proto。
解構(gòu)賦值
let [a=0, b, c] = [1, 2, 3];
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
const [a, b, c, d, e] = 'hello';
function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
// 對(duì)象
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
擴(kuò)展運(yùn)算符 ...
// 該運(yùn)算符主要用于函數(shù)調(diào)用。
function push(array, ...items) {
array.push(...items);
}
// 復(fù)制數(shù)組
const a1 = [1, 2];
// 寫法一
const a2 = [...a1];
// 寫法二
const [...a2] = a1;
//對(duì)象
let z = { a: 3, b: 4 };
let n = { ...z };
Symbol
Symbol 作為屬性名,遍歷對(duì)象的時(shí)候,該屬性不會(huì)出現(xiàn)在for...in、for...of循環(huán)中,也不會(huì)被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。
但是,它也不是私有屬性,有一個(gè)Object.getOwnPropertySymbols()方法,可以獲取指定對(duì)象的所有 Symbol 屬性名。該方法返回一個(gè)數(shù)組,成員是當(dāng)前對(duì)象的所有用作屬性名的 Symbol 值。
const obj = {};
let a = Symbol('a');
let b = Symbol('b');
obj[a] = 'Hello';
obj[b] = 'World';
const objectSymbols = Object.getOwnPropertySymbols(obj);
objectSymbols
// [Symbol(a), Symbol(b)]
Symbol.for()與Symbol()這兩種寫法,都會(huì)生成新的 Symbol。它們的區(qū)別是,前者會(huì)被登記在全局環(huán)境中供搜索,后者不會(huì)。
Symbol.for("bar") === Symbol.for("bar")
// true
Symbol("bar") === Symbol("bar")
// false
Map
需要特別注意的是,Map 的遍歷順序就是插入順序。
-Map.prototype.keys():返回鍵名的遍歷器。
-Map.prototype.values():返回鍵值的遍歷器。
-Map.prototype.entries():返回所有成員的遍歷器。
-Map.prototype.forEach():遍歷 Map 的所有成員。
// 對(duì)象轉(zhuǎn)為 Map 可以通過Object.entries()。
let obj = {"a":1, "b":2};
let map = new Map(Object.entries(obj));
WeakMap只接受對(duì)象作為鍵名(null除外),不接受其他類型的值作為鍵名。典型場(chǎng)合就是 DOM 節(jié)點(diǎn)作為鍵名
const wm = new WeakMap();
let key = {};
let obj = {foo: 1};
wm.set(key, obj);
obj = null;
wm.get(key)
// Object {foo: 1}
// WeakMap注意場(chǎng)景也是避免內(nèi)存泄漏, 上面代碼中,e1和e2是兩個(gè)對(duì)象,我們通過arr數(shù)組對(duì)這兩個(gè)對(duì)象添加一些文字說明。這就形成了arr對(duì)e1和e2的引用。
// 一旦不再需要這兩個(gè)對(duì)象,我們就必須手動(dòng)刪除這個(gè)引用,否則垃圾回收機(jī)制就不會(huì)釋放e1和e2占用的內(nèi)存。
const e1 = document.getElementById('foo');
const e2 = document.getElementById('bar');
const arr = [
[e1, 'foo 元素'],
[e2, 'bar 元素'],
];
// 不需要 e1 和 e2 的時(shí)候
// 必須手動(dòng)刪除引用
arr [0] = null;
arr [1] = null;
Set
-Set.prototype.add(value):添加某個(gè)值,返回 Set 結(jié)構(gòu)本身。
-Set.prototype.delete(value):刪除某個(gè)值,返回一個(gè)布爾值,表示刪除是否成功。
-Set.prototype.has(value):返回一個(gè)布爾值,表示該值是否為Set的成員。
-Set.prototype.clear():清除所有成員,沒有返回值。
const set = new Set([1, 2, 3, 4, 4]);
// 去除數(shù)組的重復(fù)成員
[...new Set(array)]
const items = new Set([1, 2, 3, 4, 5]);
const array = Array.from(items);
// 去除字符串里面的重復(fù)字符。
[...new Set('ababbc')].join('')
遍歷
Set.prototype.keys():返回鍵名的遍歷器
Set.prototype.values():返回鍵值的遍歷器
Set.prototype.entries():返回鍵值對(duì)的遍歷器
Set.prototype.forEach():使用回調(diào)函數(shù)遍歷每個(gè)成員
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// (a 相對(duì)于 b 的)差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
WeakSet
結(jié)構(gòu)與 Set 類似,也是不重復(fù)的值的集合。但是,它與 Set 有兩個(gè)區(qū)別。首先,WeakSet 的成員只能是對(duì)象,而不能是其他類型的值。
WeakSet 不能遍歷,是因?yàn)槌蓡T都是弱引用,隨時(shí)可能消失,遍歷機(jī)制無法保證成員的存在,很可能剛剛遍歷結(jié)束,成員就取不到了。WeakSet 的一個(gè)用處,是儲(chǔ)存 DOM 節(jié)點(diǎn),而不用擔(dān)心這些節(jié)點(diǎn)從文檔移除時(shí),會(huì)引發(fā)內(nèi)存泄漏。
const ws = new WeakSet();
ws.add(1)
// TypeError: Invalid value used in weak set
ws.add(Symbol())
// TypeError: invalid value used in weak set
Proxy代理器
用于修改某些操作的默認(rèn)行為,等同于在語言層面做出修改,所以屬于一種“元編程”(meta programming),即對(duì)編程語言進(jìn)行編程。
下面是 Proxy 支持的攔截操作一覽,一共 13 種。
get(target, propKey, receiver):攔截對(duì)象屬性的讀取,比如proxy.foo和proxy['foo']。
set(target, propKey, value, receiver):攔截對(duì)象屬性的設(shè)置,比如proxy.foo = v或proxy['foo'] = v,返回一個(gè)布爾值。
has(target, propKey):攔截propKey in proxy的操作,返回一個(gè)布爾值。
deleteProperty(target, propKey):攔截delete proxy[propKey]的操作,返回一個(gè)布爾值。
ownKeys(target):攔截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循環(huán),返回一個(gè)數(shù)組。該方法返回目標(biāo)對(duì)象所有自身的屬性的屬性名,而Object.keys()的返回結(jié)果僅包括目標(biāo)對(duì)象自身的可遍歷屬性。
getOwnPropertyDescriptor(target, propKey):攔截Object.getOwnPropertyDescriptor(proxy, propKey),返回屬性的描述對(duì)象。
defineProperty(target, propKey, propDesc):攔截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一個(gè)布爾值。
preventExtensions(target):攔截Object.preventExtensions(proxy),返回一個(gè)布爾值。
getPrototypeOf(target):攔截Object.getPrototypeOf(proxy),返回一個(gè)對(duì)象。
isExtensible(target):攔截Object.isExtensible(proxy),返回一個(gè)布爾值。
setPrototypeOf(target, proto):攔截Object.setPrototypeOf(proxy, proto),返回一個(gè)布爾值。如果目標(biāo)對(duì)象是函數(shù),那么還有兩種額外操作可以攔截。
apply(target, object, args):攔截 Proxy 實(shí)例作為函數(shù)調(diào)用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
construct(target, args):攔截 Proxy 實(shí)例作為構(gòu)造函數(shù)調(diào)用的操作,比如new proxy(...args)。
異步編程
1、回調(diào)函數(shù)
2、Promise
ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise對(duì)象。
多個(gè)請(qǐng)求 Promise.all([]).then(resArr)
3、async await ES2017 標(biāo)準(zhǔn)引入了 async 函數(shù),使得異步操作變得更加方便。
async 標(biāo)識(shí)一個(gè)function是異步函數(shù),await只能用在異步函數(shù)中,返回值是 Promise。
this問題
雖然 Proxy 可以代理針對(duì)目標(biāo)對(duì)象的訪問,但它不是目標(biāo)對(duì)象的透明代理,即不做任何攔截的情況下,也無法保證與目標(biāo)對(duì)象的行為一致。主要原因就是在 Proxy 代理的情況下,目標(biāo)對(duì)象內(nèi)部的this關(guān)鍵字會(huì)指向 Proxy 代理。
const target = {
m: function () {
console.log(this === proxy);
}
};
const handler = {};
const proxy = new Proxy(target, handler);
target.m() // false
proxy.m() // true
Reflect
Reflect對(duì)象一共有 13 個(gè)靜態(tài)方法。
Reflect.apply(target, thisArg, args)
Reflect.construct(target, args)
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)
Reflect.defineProperty(target, name, desc)
Reflect.deleteProperty(target, name)
Reflect.has(target, name)
Reflect.ownKeys(target)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf(target, prototype)
上面這些方法的作用,大部分與Object對(duì)象的同名方法的作用都是相同的,而且它與Proxy對(duì)象的方法是一一對(duì)應(yīng)的。下面是對(duì)它們的解釋。
原型
實(shí)現(xiàn)繼承的幾種方式和優(yōu)缺點(diǎn)
此問題從能夠操作原型方式解析
1、直接指定原型
1.1、通過構(gòu)造函數(shù)實(shí)現(xiàn)繼承,
優(yōu)點(diǎn):解決了子類實(shí)例共享父類引用屬性的問題;創(chuàng)建子類實(shí)例時(shí),可以向父類構(gòu)造函數(shù)傳參;
缺點(diǎn):子類實(shí)例不能繼承父類中原型對(duì)象上的屬性或者方法;無法復(fù)用父類實(shí)例屬性,
function Parent() {
this.name = 'name';
}
Parent.prototype.say = function () {
console.log('say');
}
function Child() {
Parent.call(this);
this.type = 'child';
}
const child = new Child();
child.say() // .sya is not a function
1.2、通過原型對(duì)象實(shí)現(xiàn)繼承,原型參考
缺點(diǎn):父類的屬性是引用類型時(shí),子類實(shí)例繼承的是同一份屬性,任一實(shí)例改變?cè)搶傩远紩?huì)引起全局變化,無法互相隔離
無法在不影響所有實(shí)例對(duì)象的情況下,給父類的構(gòu)造函數(shù)傳遞參數(shù)
function Parent() {
this.name = 'name';
this.favor = ['blue', 'red'];
}
Parent.prototype.say = function () {
console.log('say');
}
function Child() {
this.type = 'child';
}
Child.prototype = new Parent();
const child = new Child();
1.3 組合方式,結(jié)合了上兩種方式,避免了上面的缺點(diǎn)。但是這種方式在每次實(shí)例化子類實(shí)例時(shí),都會(huì)調(diào)用兩次父類構(gòu)造函數(shù),需要優(yōu)化。
function Parent() {
this.name = 'name';
this.favor = ['blue', 'red'];
}
Parent.prototype.say = function () {
console.log('say');
}
function Child() {
Parent.call(this);
this.type = 'child';
}
Child.prototype = new Parent();
const child = new Child();
1.4 組合優(yōu)化①
缺點(diǎn):子類實(shí)例的constructor屬性直接指向了父類構(gòu)造函數(shù),導(dǎo)致無法判斷當(dāng)前對(duì)象實(shí)例化自哪個(gè)構(gòu)造函數(shù)。
function Parent() {
this.name = 'name';
this.favor = ['blue', 'red'];
}
Parent.prototype.say = function () {
console.log('say');
}
function Child() {
Parent.call(this);
this.type = 'child';
}
Child.prototype = Parent.prototype;
const child = new Child();
1.5 組合優(yōu)化②
通過Object.create()方法指定了子類實(shí)例的proto屬性,同時(shí)顯式聲明子類的constructor
function Parent() {
this.name = 'name';
this.favor = ['blue', 'red'];
}
Parent.prototype.say = function () {
console.log('say');
}
function Child() {
Parent.call(this);
this.type = 'child';
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
const child = new Child();
2、Class
class Parent {
constructor(){
this.name = 'name';
this.favor = ['blue', 'red'];
}
say(){
console.log('say');
}
}
class Child extends Parent {
constructor() {
super()
this.type = 'child';
}
}
const child = new Child();
多重繼承:采用將多個(gè)父類屬性賦值到新的類,讓子類繼承這個(gè)新的父類
鏈判斷運(yùn)算符
const firstName = message?.body?.user?.firstName || 'default';
// 下面是判斷對(duì)象方法是否存在,如果存在就立即執(zhí)行的例子。
iterator.return?.()
//Null 判斷運(yùn)算符??
//但是只有運(yùn)算符左側(cè)的值為null或undefined時(shí),才會(huì)返回右側(cè)的值。
const headerText = response.settings.headerText ?? 'Hello, world!';
this問題,call、apply、bind
func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])
func(){}.bind(thisValue)
閉包
new函數(shù)得到一個(gè)對(duì)象的過程
1、創(chuàng)建一個(gè)空對(duì)象
2、讓空對(duì)象的proto(IE沒有該屬性)成員指向了函數(shù)的prototype成員對(duì)象
3、使用apply調(diào)用函數(shù),屬性和方法被添加到 this 引用的對(duì)象中
4、如果函數(shù)中沒有返回其它對(duì)象,那么返回 this,即創(chuàng)建的這個(gè)的新對(duì)象,否則,返回構(gòu)造函數(shù)中返回的對(duì)象
function _new() {
let obj= {}; // 創(chuàng)建的新對(duì)象
// 第一個(gè)參數(shù)是構(gòu)造函數(shù)
let [constructor, ...args] = [...arguments];
// 執(zhí)行 [[原型]] 連接 ;實(shí)際上就是生產(chǎn)了一個(gè)新的上下文
obj.__proto__ = constructor.prototype;
// 使用apply在obj作用域中調(diào)用構(gòu)造器函數(shù),屬性和方法被添加到 this 引用的對(duì)象即obj中
let result = constructor.apply(obj, args);
if (result && (typeof (result) == "object" || typeof (result) == "function")) {
// 如果構(gòu)造函數(shù)執(zhí)行的結(jié)果返回的是一個(gè)對(duì)象,那么返回這個(gè)對(duì)象
return result;
}
// 如果構(gòu)造函數(shù)返回的不是一個(gè)對(duì)象,返回創(chuàng)建的新對(duì)象
return obj;
}
結(jié)合下面的代碼片段來具體分析下:
function Person(age){
this.age= age;
console.log(this);
return {age:age};//返回對(duì)象
}
Person.prototype.index = 1
var person1 = new Person(20); // 此處相當(dāng)于var person1=_new(Person, 20)
var person2 = Person(18);
console.log(person1);
console.log(person2);
console.log('p1.index=', person1.index)
console.log('p2.index=', person2.index)
設(shè)計(jì)模式
- 發(fā)布訂閱:如 vue 中的雙向綁定實(shí)現(xiàn)
- 單例 如: 導(dǎo)出一個(gè)模塊
- 裝飾者:在不改變對(duì)象自身的基礎(chǔ)上,動(dòng)態(tài)的給某個(gè)對(duì)象添加額外的職責(zé),不會(huì)影響原有接口的功能。如* react中的高階組件
- 代理模式: 如vue中對(duì)data屬性的代理,ES6的 Proxy
- 命令模式:指的是 一個(gè)執(zhí)行某些待定事情的指令, 用一種松耦合的方式來設(shè)計(jì)程序,使得請(qǐng)求發(fā)送者和請(qǐng)求接收者能夠消除彼此之間的耦合關(guān)系。如websocket發(fā)送請(qǐng)求與接收請(qǐng)求處理
- 外觀模式:為子系統(tǒng)中的一組接口提供一個(gè)一致的界面,定義一個(gè)高層接口,這個(gè)接口使子系統(tǒng)更加容易使用。外觀模式在JS中,可以認(rèn)為是一組函數(shù)的集合。
深拷貝實(shí)現(xiàn)方式 循環(huán)引用問題怎么解決
1、遞歸
2、迭代,參考
3、JSON.stringify JSON.parse
4、使用第三方庫 如 lodash
循環(huán)引用可在外部定義一個(gè)數(shù)組保存已復(fù)制過的值,在深拷貝前判斷是否在數(shù)組中,在的話就設(shè)置為這個(gè)值,不在再執(zhí)行深拷貝
跨域
頁面跨域通信幾種方式
1、window.postMessage
2、window.name
3、document.domain (限制在一級(jí)域名一樣)
4、Hash傳參 (A修改B url Hash值,B監(jiān)聽onhashchange)
接口跨域問題
1、添加允許跨域頭信息
2、服務(wù)端使用代理
3、JSONP
添加事件方法
- dom節(jié)點(diǎn)直接綁定
<a onclick="func">點(diǎn)擊</a> - addEventListener(type, listener, {capture:捕獲階段觸發(fā), once:, })
- addEventListener(type, listener, useCapture:false(在捕獲階段執(zhí)行))
- IE7/8: attachEvent('on'+type, listener)
阻止事件冒泡與默認(rèn)行為
- 阻止事件冒泡:e.stopPropagation() IE: window.event.cancelBubble = true
- 阻止事件默認(rèn)行為 e.preventDefault() IE: window.event.returnValue == false;
數(shù)組去重
一個(gè)頁面從輸入 URL 到頁面加載顯示完成,這個(gè)過程中都發(fā)生了什么?
檢查是否有緩存->瀏覽器發(fā)出請(qǐng)求->dns解析->得到解析后ip機(jī)器端口->建立tcp/ip連接->瀏覽器發(fā)起HttpGet請(qǐng)求->WebServer接受到請(qǐng)求->原路返回->瀏覽器處理(302、404等)->展示
-可同步發(fā)起多少請(qǐng)求?是瀏覽器而定,同一個(gè)域名一般6-7個(gè)。所以為了加快資源下載速度,通常將靜態(tài)資源放入單獨(dú)的dns服務(wù)器
-如何利用緩存:
1. 強(qiáng)制緩存判斷HTTP首部字段:cache-control,Expires。
-Expires是一個(gè)絕對(duì)時(shí)間,即服務(wù)器時(shí)間。瀏覽器檢查當(dāng)前時(shí)間,如果還沒到失效時(shí)間就直接使用緩存文件。但是該方法存在一個(gè)問題:服務(wù)器時(shí)間與客戶端時(shí)間可能不一致。因此該字段已經(jīng)很少使用。
cache-control中的max-age保存一個(gè)相對(duì)時(shí)間。例如Cache-Control: max-age = 484200,表示瀏覽器收到文件后,緩存在484200s內(nèi)均有效。如果同時(shí)存在cache-control和Expires,瀏覽器總是優(yōu)先使用cache-control。
2. 協(xié)商緩存,每次發(fā)請(qǐng)求到服務(wù)器確認(rèn)。對(duì)比緩存通過HTTP的last-modified,Etag字段進(jìn)行判斷。
-last-modified是第一次請(qǐng)求資源時(shí),服務(wù)器返回的字段,表示最后一次更新的時(shí)間。下一次瀏覽器請(qǐng)求資源時(shí)就發(fā)送if-modified-since字段。服務(wù)器用本地Last-modified時(shí)間與if-modified-since時(shí)間比較,如果不一致則認(rèn)為緩存已過期并返回新資源給瀏覽器;如果時(shí)間一致則發(fā)送304狀態(tài)碼,讓瀏覽器繼續(xù)使用緩存。
-Etag:資源的實(shí)體標(biāo)識(shí)(哈希字符串),當(dāng)資源內(nèi)容更新時(shí),Etag會(huì)改變。服務(wù)器會(huì)判斷Etag是否發(fā)生變化,如果變化則返回新資源,否則返回304。
方案:html使用協(xié)商緩存,css&js&圖片 使用強(qiáng)緩存,文件命名帶上hash值
實(shí)際上單頁應(yīng)用:html強(qiáng)制設(shè)置不緩存,資源文件默認(rèn)瀏覽器緩存,并設(shè)置了Last-Modified: 和 ETag
安全
XSS
跨站腳本攻擊(Cross Site Scripting)是最常見和基本的攻擊 WEB 網(wǎng)站方法,攻擊者通過注入非法的 html 標(biāo)簽或者 javascript 代碼,從而當(dāng)用戶瀏覽該網(wǎng)頁時(shí),控制用戶瀏覽器。
- 通過表單保存惡意腳本后,在瀏覽器執(zhí)行。獲取用戶cookie等信息或?qū)W(wǎng)站正常功能進(jìn)行破壞
- 防御
-cookie設(shè)置為httpOnly
-對(duì)輸入編碼后存在數(shù)據(jù)庫
CSRF
跨站點(diǎn)請(qǐng)求偽造(Cross-Site Request Forgeries),也被稱為 one-click attack 或者 session riding。冒充用戶發(fā)起請(qǐng)求(在用戶不知情的情況下), 完成一些違背用戶意愿的事情(如修改用戶信息,刪初評(píng)論等)。
- 通過引誘用戶點(diǎn)擊惡意鏈接,發(fā)起惡意請(qǐng)求,此時(shí)會(huì)帶上cookie
- 防御:
-驗(yàn)證碼
-referer check
-token
點(diǎn)擊劫持
點(diǎn)擊劫持是一種視覺欺騙的攻擊手段。攻擊者將需要攻擊的網(wǎng)站通過 iframe 嵌套的方式嵌入自己的網(wǎng)頁中,并將 iframe 設(shè)置為透明,在頁面中透出一個(gè)按鈕誘導(dǎo)用戶點(diǎn)擊。
- 設(shè)置http響應(yīng)頭X-FRAME-OPTIONS,方式被嵌入其他網(wǎng)站
-DENY,表示頁面不允許通過 iframe 的方式展示
-SAMEORIGIN,表示頁面可以在相同域名下通過 iframe 的方式展示
-ALLOW-FROM,表示頁面可以在指定來源的 iframe 中展示
SQL注入
就是后端依賴前端返回的參數(shù)直接拼接sql進(jìn)行查詢數(shù)據(jù),導(dǎo)致sql不正常的拼接,造成的安全問題。
防御:對(duì)前端傳遞的信息進(jìn)行層層校驗(yàn),不直接使用。
TCP/IP
TCP:
1、有狀態(tài)的連接
2、只能是一對(duì)一通信
3、適用于要求可靠傳輸?shù)膽?yīng)用,例如文件傳輸
三次握手:
-客戶端向服務(wù)端發(fā)送連接請(qǐng)求:SYN=1,Seq=隨機(jī)數(shù)J
-服務(wù)端收到連接請(qǐng)求,確認(rèn)可以連接,發(fā)送:SYN=1,ACK=1,ack=J+1,seq=隨機(jī)數(shù)N
-客戶端收到請(qǐng)求,確認(rèn)連接:發(fā)送應(yīng)答:ACK=1,ack=N+1
四次揮手(全雙工在斷開連接時(shí)兩端都需要發(fā)送 FIN 和 ACK。)
-客戶端發(fā)送關(guān)閉請(qǐng)求:FIN=J
-服務(wù)端確認(rèn)關(guān)閉應(yīng)答:ack=J+1,ACK=1 (此時(shí)客戶端不可在發(fā)送數(shù)據(jù),可以接受數(shù)據(jù))
-服務(wù)端發(fā)送關(guān)閉請(qǐng)求:FIN=N
-客戶端確認(rèn)關(guān)閉應(yīng)答:ack=N+1,ACK=1(此時(shí)連接互相關(guān)閉)
UDP:
1、無狀態(tài)連接
2、有單播,多播,廣播的功能
3、UDP是面向報(bào)文的
4、不可靠性
5、頭部開銷小,傳輸數(shù)據(jù)報(bào)文時(shí)是很高效的。
http2
https
vue
生命周期
vue: beforeCreate created mounted beforeUpdate updated activated deactivated beforeDestroy destroyed errorCaptured
vue-router: beforeRouteEnter, beforeRouteUpdate, beforeRouteLeave
雙向綁定原理、如何實(shí)現(xiàn)數(shù)組的雙向綁定
利用了Object.defineProperties 劫持了 get set。在get里收集依賴,在set里通知依賴更新,所以只支持IE9+
缺點(diǎn):
- 需要對(duì)數(shù)組的一些方法改寫
- 無法監(jiān)測(cè)數(shù)組下標(biāo)直接賦值和長(zhǎng)度修改
- 無法監(jiān)聽到對(duì)象新增的屬性和刪除屬性
vue-next 使用了新的 Proxy 實(shí)現(xiàn)雙向綁定,只支持IE12+
Proxy優(yōu)點(diǎn)有:
-對(duì)數(shù)據(jù)也能監(jiān)測(cè)到
-性能更好,不需要2.x遍歷屬性然后再劫持
-有更全面的方法
keep-alive原理
key的作用
-使列表渲染時(shí)針對(duì)虛擬don的diff算法更有效,減少不必要的更新
-賦值不同的值,可強(qiáng)制使組件重新渲染
組件間通信
- prop、自定義事件
- refs、children等
- 自定義個(gè)發(fā)布訂閱對(duì)象
自定義指令
一個(gè)指令定義對(duì)象可以提供如下幾個(gè)鉤子函數(shù) (均為可選):
bind:只調(diào)用一次,指令第一次綁定到元素時(shí)調(diào)用。在這里可以進(jìn)行一次性的初始化設(shè)置。
inserted:被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用 (僅保證父節(jié)點(diǎn)存在,但不一定已被插入文檔中)。
update:所在組件的 VNode 更新時(shí)調(diào)用,但是可能發(fā)生在其子 VNode 更新之前。指令的值可能發(fā)生了改變,也可能沒有。但是你可以通過比較更新前后的值來忽略不必要的模板更新 (詳細(xì)的鉤子函數(shù)參數(shù)見下)。
componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用。
unbind:只調(diào)用一次,指令與元素解綁時(shí)調(diào)用。
component動(dòng)態(tài)組件原理
自定義常見業(yè)務(wù)組件
react
生命周期
掛載
constructor()
static getDerivedStateFromProps()
render()
componentDidMount()
更新
static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
卸載
componentWillUnmount()
錯(cuò)誤處理
static getDerivedStateFromError()
componentDidCatch()
高階組件
高階組件是參數(shù)為組件,返回值為新組件的函數(shù)。
例如 Redux 的 connect
Hook
為函數(shù)式組件使用,與class組件對(duì)比的優(yōu)缺點(diǎn)
useState
useEffect -- 相當(dāng)于componentDidMount、componentDidUpdate 和 componentWillUnmount周期鉤子
taro
flutter
獲取微信用戶id、用戶名、授權(quán)
微信支付
支付寶支付
shell 3劍客
grep '字符' 文件 (過濾)
sed '命令' 文件 (實(shí)現(xiàn)數(shù)據(jù)的替換,刪除,增加,選取等(以行為單位進(jìn)行處理))
awk '條件{命令}' 文件 (AWK 是一種處理文本文件的語言,是一個(gè)強(qiáng)大的文本分析工具。)
awk [選項(xiàng)參數(shù)] 'script' var=value file(s) 或 awk [選項(xiàng)參數(shù)] -f scriptfile var=value file(s)
linux 資源查看
查看磁盤情況
df -a(所有文件系統(tǒng),包括虛擬)
df -h 以K M G單位顯示
du -sh xx 查看指定文件大小
查看內(nèi)存情況
free -h
top
查看CPU情況
top
關(guān)閉進(jìn)程 kill pid
查找nodejs進(jìn)程,并查看進(jìn)程相關(guān)資源信息
ps -ef | grep node
pidstat -r(內(nèi)存)u(CPU)d(IO情況) -p 1875(pid) 1(刷新頻率)
查看java進(jìn)程
ps -ef | grep java
pidstat -r(內(nèi)存)u(CPU)d(IO情況) -p 1875(pid) 1(刷新頻率)