目錄javascript
塊級元素css
行內元素html
行內塊級元素前端
h5java
// html <div class="left"></div> <div class="right"></div>
第一種方法:浮動css3
.left { float: left; width: 200px; height: 500px; background: darkcyan; } .right { height: 500px; background: deepskyblue; }
第二種方法:絕對定位git
body { position: relative; } .left { position: absolute; left: 0; top: 0; width: 200px; height: 500px; background: darkcyan; } .right { height: 500px; background: deepskyblue; }
第三種方法:flexes6
.parent { display: flex; } .left { width: 200px; height: 500px; background: darkcyan; } .right { height: 500px; background: deepskyblue; flex-grow: 1; }
.radius(@r:50%) { -webkit-border-radius: @r; -moz-border-radius: @r; border-radius: @r; }
IE67的混雜模式,寬度是算上了border + paddingweb
width = border-left + padding-left + con_width + padding-right + border-right
標準盒模型是分開來計算的面試
content-box 是w3c標準盒模型,其中的margin border padding width都是分別計算的,其中的width屬性是隻針對content的寬度。而border-box是IE67的混雜模型的盒模型計算方式,其中的width屬性是盒模型的border + padding + content
div { -webkit-box-shadow: inset 5px 0 3px deepskyblue; -moz-box-shadow: inset 5px 0 3px deepskyblue; box-shadow: inset 5px 0 3px deepskyblue; }
box-shadow: inset h v blur spreed color
內陰影 豎直 水平 模糊 半徑 顏色
link -> visited -> hover -> active
緣由以下:link和visited是常態,hover和active是即時狀態,即時狀態想要覆蓋常態就必需要放到後面,不然無效。
一樣,在常態裏,visited是訪問後的狀態,想要覆蓋未訪問狀態就要寫到其後面;
即時態裏,active想要覆蓋hover就要寫到後面
display: flex
設置這個屬性後就會成爲flex怪異盒模型
flex-direction
設置flex主軸的方向,屬性值有:row/row-reverse/colum/colum-reverse
flex-wrap
設置換行的方式,屬性值有:nowrap/wrap/wrap-reverse
justify-content
align-items
align-content
多根軸的對齊方式,若是隻有一根軸就不生效order
數值越小越靠前,默認爲0flex-grow
放大比例,如何去分配默認空間,0不放大,1均分,若是按其餘比例,能夠單獨給項目設置flex-shrink
縮小比例,0不縮小,1等比例縮小,默認值是1複合寫法是flex
align-self
單獨設置對齊方式相關知識點:
跨域是瀏覽器的行爲
跨域須要服務端的配合,若是不能修改服務端,能夠本身後臺轉發一下請求,畢竟後臺請求是沒有跨域限制的
跨域的方式有幾種,面試官要是問跨域的方式的話,通常就是在問JSONP。和麪試官講請JSONP的原理也算一點加分項。
相關知識點:
總而言之,就是使用script標籤把數據請求回來。
通常印象中,script標籤就是外鏈一段js代碼。如今寫一個服務,當瀏覽器訪問/js
時,就send('alert("js")')
,發送一段js代碼。如今看是否會執行
能夠看到js代碼正常執行了。這個就等於直接往全局做用域裏直接寫了一行alert('js')
這個時候咱們再返回一個JSON串回去
能夠看到,直接報錯了。這個就比如,直接往全局做用域裏直接赤裸裸的扔了一個對象,沒有任務操做。
假如咱們在全局做用域裏已經定義好了一個函數
function handle(data) { console.log(data); }
若是用script標籤請求回來的數據,能直接用這個函數處理多好。因此後臺給咱們處理的時候
res.send('handle({name: "chang"})')
這個返回的數據和上面同樣,也至關於直接在全局做用域裏寫了個
handle({name: "chang"});
這個時候咱們早已經定義好了處理函數,那麼這個函數就能夠直接處理數據了
因此無論哪一個工具封裝的JSONP都是這個操做,也就是爲何要和後臺定義回調函數的名稱,由於後臺不知道你在JS定義什麼名稱的函數來處理數據,通常這個回調函數名稱是須要放在queryString
中的。後臺須要截取,再拼接
如下就是簡單的JSONP代碼
function xxxx(content) { console.log(content); } let script = document.createElement('script'); script.src = 'http://127.0.0.1:8000?cb=xxxx'; document.body.appendChild(script);
因此綜上,jsonp只能是get請求
fetch是以前瀏覽器的xhr
對象的替代方案,如今使用的話,有瀏覽器兼容問題,畢竟有些瀏覽器是不支持的,可使用whatwg-fetch
這個包來解決一下。
和原生的xhr同樣,都不會直接使用原生,而是使用封裝好的庫。
和原生的xhr
相比,優勢:
async/await
,寫的就像同步代碼同樣爽try { let response = await fetch(url); let data = await response.json(); console.log(data); } catch(e) { console.log("error:", e); }
使用的坑:
fetch(url, {credentials: 'same-origin'})
同域下發送cookiefetch(url, {credentials: 'include'})
跨域下發送cookie一種先後臺通訊的方案,後臺能夠主動給前臺推送消息,而取代以前的短輪循和長輪循
說出下面數字的輸出順序:
console.time('setTimeout'); console.time('setImmediate'); setImmediate(() => { console.log(1); console.timeEnd('setImmediate'); }); setTimeout(() => { console.log(2); console.timeEnd('setTimeout'); }, 0); process.nextTick(() => console.log(3)); new Promise(function(resolve){ console.log(4); resolve(); console.log(5); }).then(function(){ console.log(6); }); (() => console.log(7))();
答案:
4 5 7 3 6 2 1
解析:同步代碼先順序執行,而後是本輪循環的異步任務和次輪循環的異步任務。
process.nextTick
和Promise
就屬於本輪循環的,並且process.nextTick
最早執行
其餘兩個屬性次輪循環的異步任務,在setTimeout
的延遲時間爲4ms及如下時,setTimeout
會先執行
var k; for (var i = 0, j = 0; i < 7, j < 10; i++, j++) { k = i + j; } console.log(k); var l; for (var i = 0, j = 0; i < 10, j < 7; i++, j++) { l = i + j; } console.log(l);
alert的時候會自動調用toString()
方法
alert([1, 3]); // -> 1, 3 alert({name: 'chang'}); // -> [object Object]
for (var i = 0; i < 5; i++) { setTimeout(function () { console.log(i); }, 1000*i); }
結果是連續輸出5個5。setTimeout執行時,i已是5了,所有輸出5很正常,如今的問題是時間間隔是多少。正確的姿式是,間隔時間是不相同的。(實驗得知)
var obj = {name: 'Joo', age: 30}; ~function (n) { console.log(n); n.name = '中國'; n = {}; n.age = 5000; console.log(n); }(obj); console.log(obj);// {name: 'Joo', age: 30} // 形參 形式上的一個表明值 // 解耦 function add(a, b) { console.log(arguments.callee.caller); } // 實參 實際傳入的參數 function a() { add(1, 4); } a();
方法 | 參數 | 返回值 | 是否影響原數組 | 發佈版本 |
---|---|---|---|---|
push | length | y | ||
pop | item | y | ||
shift | item | y | ||
unshift | length | y | ||
splice | ||||
slice | ||||
concat | ||||
sort | ||||
toString | ||||
join | ||||
reverse | ||||
indexOf/lastIndexOf | ||||
forEach | ||||
every | ||||
some | ||||
filter | ||||
map | ||||
reduce/reduceRight | ||||
find/findIndex | ||||
includes | ||||
fill | ||||
entries/keys | ||||
Array.from | ||||
Array.of |
第一種方法:使用遞歸
var arr = [1, 2, [3, 4, [5, 6], 7], 8, [9, 10, [11]], 12]; var spreadArr = []; function spread(arr) { for (var i = 0; i < arr.length; i++) { if (arr[i] instanceof Array) { spread(arr[i]); } else { spreadArr.push(arr[i]); } } } spread(arr); console.log(spreadArr);
function bubbleSort(arr) { let isCompleted = true; for (let i = 0; i < arr.length - 1; i++) { for (let j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; isCompleted = false; } } if (isCompleted) { console.log('提早完成'); return arr; } else { isCompleted = true; } } isCompleted = null; return arr; }
function insertSort(arr) { let newArr = [arr[0]]; for (let i = 1; i < arr.length; i++) { let cur = arr[i]; for (let j = 0; j < newArr.length;) { if (cur > newArr[j]) { j++; if (j === newArr.length) { newArr.push(cur); break; } } else { newArr.splice(j, 0, cur); break; } } } return newArr; }
function quickSort(arr) { if (arr.length <= 1) { return arr; } let midIndex = Math.ceil(arr.length / 2); let midVal = arr.splice(midIndex, 1)[0]; let left = [], right = []; for (let i = 0; i < arr.length; i++) { let cur = arr[i]; cur < midVal ? left.push(cur) : right.push(cur); } return quickSort(left).concat(midVal, quickSort(right)); }
function unique2(arr) { let obj = {}; for (let i = 0; i < arr.length; i++) { let cur = arr[i]; if (obj[cur] === cur) { arr.splice(i, 1); i--; } else { obj[cur] = cur; } } return arr; }
function A(name) { this.name = name; this.sex = 1; } A.prototype.say = function () { console.log('hello world'); }; function B(age) { this.age = age; } let a = new A(); B.prototype = a; let b = new B(18); console.log(b);//{ age: 18 } console.log(b.name, b.sex);//undefined 1 b.say();//hello world /* * 原型鏈繼承:子類的原型指定父類的實例 * * extend:繼承了父類的私有和公有屬性,在此處name和sex是私有屬性,say是公有屬性 * - 私有屬性是從父類的實例上獲得的 * - 公的屬性是沿着做用域鏈b.__proto__ --> a (沒有) --> a.__proto__ --> A.prototype (保存在此處) * * 原型鏈繼承的問題: * - 繼承父類的私有屬性時,沒法向父類型中傳參,因此在輸出b.name的時候是undefined * - 在繼承引用數據類型的值時,就會有問題,請看下例 * */ function SuperType() { this.color = ['red', 'blue', 'yellow']; } function SubType() { } SubType.prototype = new SuperType(); let instance1 = new SubType(); let instance2 = new SubType(); instance1.color.push('black'); console.log(instance2.color);//[ 'red', 'blue', 'yellow', 'black' ] //修改了instance1的屬性的時候instance2的屬性也會跟着變化,由於這個屬性都是來自於它們的原型
function SuperType(age) { this.age = age; } SuperType.prototype.say = function () { console.log('hello world'); }; function SubType(age) { SuperType.call(this, age); } let sub = new SubType(18); console.log(sub);//SubType { age: 18 } console.log(sub.say);//undefined /* * call繼承:讓父類的構造函數在子類的構造函數裏執行,並使用call改變裏面的this * * extend:由於只是讓父類的構造函數在子類裏執行,因此只繼承了私有屬性。 * * 優勢:和原型鏈繼承相比,解決了沒法傳參的問題,這個參數能夠寫在call的第二個參數位置 * * 缺點: * - 由於只有私有屬性繼承,定義在父類原型上的方法對子類的實例都是不可見的 * */
function SuperType() { this.name = 'chang'; } SuperType.prototype.say = function () { console.log('hello'); }; function SubType() { SuperType.call(this); } SubType.prototype = new SuperType(); let sub = new SubType(); console.log(sub);//{ name: 'chang' } sub.say();//hello /* * 組合式繼承:將原型繼承和call繼承組合使用 * * extend:使用call繼承私有屬性,使用原型鏈繼承繼承公有屬性 * * 優勢:解決了原型繼承和call繼承的問題 * * 缺點:父類的構造函數調用了兩次 * * */
/* * 這種方法並無使用嚴格意義上的構造函數,藉助原型能夠基於已有的對象創新新的對象,同時還沒必要建立自定義的類型 * */ function object(o) { function F() { } F.prototype = o; return new F(); } let obj1 = {name: 'chang', friend: ['a', 'b', 'c']}; let obj2 = object(obj1); console.log(obj2.__proto__);//{ name: 'chang', friend: [ 'a', 'b', 'c' ] } /* * 在es5中規範了這個繼承的方法:Object.create(),這個方法接收兩個參數,一個用做新對象原型的對象和(可選的)一個爲新對象定義額外屬性的對象 * */ let obj3 = Object.create(obj1); console.log(obj3.__proto__);//{ name: 'chang', friend: [ 'a', 'b', 'c' ] } //添加額外屬性時,必須使用這種格式 let obj4 = Object.create(obj1, { like: { value: 'code' } }); console.log(obj4.like);//code
__proto__
function SuperType() { this.name = 'chang'; } SuperType.prototype.say = function () { console.log('ok'); }; function SubType() { } SubType.prototype.__proto__ = SuperType.prototype; let sub = new SubType(); console.log(sub.name);//undefined sub.say();//ok /* * 不知道名字的繼承:改變子類的原型的__proto__,指向父類的原型 * 只繼承公有 * */
setProtoOf
/* * Object.setPrototypeOf方法的做用與__proto__相同,用來設置一個對象的prototype對象,返回參數對象自己。它是 ES6 正式推薦的設置原型對象的方法。 * * * */ let obj1 = {name: 'chang'}; let obj2 = {}; Object.setPrototypeOf(obj2, obj1); console.log(obj2.__proto__ === obj1);
var os = document.getElementsByTagName('*'); var cObj = {}; var max = 0; function sta(cName) { var cNameArr = cName.split(/ +/); for (var i = 0; i < cNameArr.length; i++) { var cur = cNameArr[i]; if (cObj[cur]) { cObj[cur]++; } else { cObj[cur] = 1; } } } for (var i = 0; i < os.length; i++) { if (os[i].className) { sta(os[i].className); } } for (var attr in cObj) { if (cObj.hasOwnProperty(attr)) { if (cObj[attr] > max) { max = cObj[attr]; } } } console.log(max);
let/const
includes/startsWith/endsWith
repeat
entries/keys/values
Array.from
將類數組轉化成數組Array.of
將一級值轉成數組includes
Object.assign
合併對象,淺拷貝Object.keys()/Object.values()/Object.entries()
Symbol
第6種基本數據類型的值 let s = Symbol() // 不須要new
Set
可用於數組去重var arr = [1, 1, 1, 1]; var s = new Set(arr); var newArr = [...s];
Map
和Object
相比,key值能夠是任何值proxy
作目標對象的讀寫操做的攔截Promise
async/await
Class/extends
Module
經常使用命令(結合本身經常使用)
git add
git commit
git pull
git push
在多人協做開發的時候,若是不pull
是絕對push
不上去的git log
git log --pretty=oneline
git log --author=changzhn
git log -- filename
git log --grep=xxx
git show hash
查看當前的分支
git branch
git checkout -b develop
git checkout develop/release/master
git status
add
和commit
來產生版本號後,才能切換分支git stash
git stash list
git stash pop stash@{0}
好比切到release
分支上想合併develop
分支
git merge develop
找到版本號的時候想回退代碼
git reset --HARD hash
push
上去,這個時候發現是推不上去的。git push origin master -f
-f
來暴力提交