CSS
-
解釋 css 各種定位,absolute 相對於誰定位;
-> position: relative/absolute/fixed/static/inherit/initial/unset/sticky
-> 相對於最近一層position非static的父元素
-> relative不會脫離文檔流 -
iframe 中的 fixed 定位和什么有關,怎么固定瀏覽器窗口
-> iframe窗口非瀏覽器窗口,通過postmessage通信將top頁面的scrolltop傳遞給iframe,iframe內部通過監聽通訊事件動態設置元素的定 -
transfrom 的主要用法
-> transform用來向元素應用各種2D和3D轉換,該屬性允許我們對元素進行旋轉、縮放、移動或傾斜等操作,有translate, scale, rotate, skew, -
flex 盒子布局
flex 布局詳解 -
不同高的子盒子實現頭部對齊
// 1. padding 補償
.parent {
width: 100%;
overflow: hidden;
}
.left, right {
float: left;
padding-bottom:9999px;
margin-bottom:-9999px;
}
// 2. flex 布局
.parent{
display: flex;
}
-
css 盒模型;
-> 標准盒子模型:寬度=內容的寬度(content)+ border + padding + margin -> box-sizing:content-box;
-> 低版本IE盒子模型:寬度=內容寬度(content+border+padding)+ margin -> box-sizing:border-box;; -
重繪和回流的區別
-> 重繪(repaint):當render tree中的一些元素需要更新屬性,單這些屬性只會影響元素的外觀,風格,而不會影響到元素的布局,此類的頁面渲染叫作頁面重繪。
-> 回流(reflow):當render tree中的一部分(或全部)因為元素的規模尺寸,布局,隱藏等改變而引起的頁面重新渲染。
-> 回流必將引起重繪,而重繪不一定會引起回流 -
如何解決外邊距重合問題;
-> 外邊距重疊是指兩個或多個盒子(可能相鄰也可能嵌套)的相鄰邊界(其間沒有任何非空內容、補白、邊框)重合在一起而形成一個單一邊界
外層元素添加padding;
外層元素 overflow:hidden;
外層元素透明邊框 border:1px solid transparent;
內層元素絕對定位 postion:absolute;
內層元素 加float:left;或display:inline-block; -
清除浮動
1、父級div定義overflow: auto;;
2、.clearfix -
兩列布局(右側定寬200px,左邊隨屏幕自動填充寬度)
// 1. float+margin(一側定寬,一側自動)
// 2. position+margin(一側定寬,一側自動)
// 3. float+負margin(一側定寬,一側自動)
.right {
float:left;
width: 100%;
}
.right .cont {
margin-left:200px;
}
.left {
float: left;
width: 200px;
margin-left: -100%;
}
- 三列布局
// 1. float+margin(兩側定寬,中間自適應)
// 2. position+margin(兩側定寬,中間自適應)
// 3. float+負margin(兩側定寬,中間自適應)
.m-box {
float:left;
width: 100%;
}
.m-box .center {
margin:0 200px;
}
.left,.right {
float: left;
width: 200px;
margin-left: -100%;
}
.right {
margin-left: -200px;
}
- 垂直水平居中
// 1、絕對定位+margin:auto
.box {
margin: auto;
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
}
// 2、絕對定位+transform反向偏移
.box {
margin: auto;
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
// 3、display: flex-box
.box {
display: flex;
align-items: center;
justify-content: center;
}
- css 實現4:3的塊元素
.box {
width: 100%;
height: 0;
padding-top: 75%;
}
- css寫個無限旋轉動畫
.ig{
-webkit-animation:circle 1.5s infinite linear;
}
@-webkit-keyframes circle{
0%{ transform:rotate(0deg); }
100%{ transform:rotate(360deg); }
}
- 用css畫一個三角形
.triangle{
width: 0; height:0;
border: 10px solid transparent;
border-top-color: red;
}
簡答題
- 自我介紹,項目介紹,項目中的難點以及解決方案;
- 項目中遇到的技術問題
- 最近在學什么東西
- MVC/MVVM 的理解
- 問了h5語義化的問題
- 為什么用來React又用jquery
- Reat寫組件有挑戰性的東西
- 關鍵詞標記顏色
- amd 和 cmd 規范理解;
- es6相比es5有沒有什么比較好的特性
- 箭頭函數和一般函數的區別
- promise了解不
- JS的數據類型
-> number,boolean,string,undefined,null,object,symbol。 - 發http請求會怎么做
- 常見的狀態碼
- http緩存怎么做到的
- 瀏覽器緩存常見的http的頭 requestHeader
- 性能優化的事情
- 打包工具 Webpack 的配置,原理,webpack優化;
-> 解析webpack配置參數,合並從shell傳入和webpack.config.js文件里配置的參數,生產最后的配置結果。
-> 注冊所有配置的插件,好讓插件監聽webpack構建生命周期的事件節點,以做出對應的反應。
-> 從配置的entry入口文件開始解析文件構建AST語法樹,找出每個文件所依賴的文件,遞歸下去。
-> 在解析文件遞歸的過程中根據文件類型和loader配置找出合適的loader用來對文件進行轉換。
-> 遞歸完后得到每個文件的最終結果,根據entry配置生成代碼塊chunk。
-> 輸出所有chunk到文件系統。 - nodeJS
- 講講同源策略
- url構成,解析一個url,包括hash值;
- post和get的區別
- 事件代理是什么事件代理中target和event細節
- 原型鏈繼承對象、構造函數、prototype、_proto
- http1.0 ,1.1,2.0的區別;
- Object.defineProperty()的缺點;
- post content-type類型
- 然后問了冒泡,捕獲;
- 手寫一個閉包;
- 考察數組判定、
- 一道異步代碼題,說出打印順序;
- 三個url同時請求,要求按順序打印結果
- http緩存優缺點
- 單頁應用優缺點
- 瀏覽器緩存優缺點
- addEventListener()有幾個參數,是什么?
- typeof的類型(舉例說屬於什么類型)
- 問針對移動瀏覽器端開發頁面,不期望用戶放大屏幕,且要求“視口(viewport)”寬度等於屏幕寬度,視口高度等於設備高度,如何設置?
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1,
maximum-scale=1, user-scalable=no">
- == 與 === 的區別;
- cookie是什么,怎么存儲。
- cookie和session的區別;
- 問請描述一下cookies,sessionStorage和localStorage的區別?
答:cookie:一般由服務器生成,可設置失效時間。如果在瀏覽器端生成Cookie,默認是關閉瀏覽器后失效,也可設置過期時間,每次都會攜帶在HTTP頭中,如果使用cookie保存過多數據會帶來性能問題 sessionStorage: 僅在當前會話下有效,關閉頁面或瀏覽器后被清除 localStorage: 除非被清除,否則永久保存,僅在客戶端(即瀏覽器)中保存,不參與和服務器的通信 - 介紹H5的兩個瀏覽器緩存,localStorage和sessionStorage的區別。
保存數據的生命周期不同。 sessionStorage只是可以將一部分數據在當前會話中保存下來,刷新頁面數據依舊存在。但當頁面關閉后,sessionStorage 中的數據就會被清空 - fetch和ajax的區別。
1、fetch()返回的promise將不會拒絕http的錯誤狀態,即使響應是一個HTTP 404或者500。 服務器端返回 狀態碼 400 500的時候 不會reject Response.ok 屬性為 true。
2、在默認情況下 fetch不會接受或者發送cookies ,要發送 cookies,必須設置 credentials 選項。 credentials: 'include' - Bom是什么,列舉你知道的Bom對象;
- function.prototype.bind/call/apply的用法及區別
- 問什么是瀏覽器的標准模式和怪異模式
答:目前瀏覽器的排版引擎有三種模式:怪異模式(Quirks mode)、接近標准模式(Almost standards mode)、以及標准模式(Standards mode)。在怪異模式下,排版會模擬 Navigator 4 與 Internet Explorer 5 的非標准行為。為了支持在網絡標准被廣泛采用前,就已經建好的網站,這么做是必要的。在標准模式下,行為即(但願如此)由 HTML 與 CSS 的規范描述的行為。在接近標准模式下,只有少數的怪異行為被實現。 那么所謂標准模式,就一定都“標准”嗎?答案當然是否定的,因為各個瀏覽器廠商實現標准的階段不同,所以各個瀏覽器的“標准模式”之間也會有很大的不同。 Firefox、Safari、Chrome、Opera (自 7.5 以后)、 IE8 和 IE9 都有一個准標准模式。那么既然標准模式都不那么標准,准標准的模式肯定就更不標准了。 - 問解釋一下盒模型寬高值的計算方式,邊界塌陷,負值作用,box-sizing概念
答:盒模型 a. ie678怪異模式(不添加 doctype)使用 ie 盒模型,寬度=邊框+padding+內容寬度 b. chrome, ie9+, ie678(添加 doctype) 使用標准盒模型,寬度= 內容寬度 box-sizing content-box(默認) 布局所占寬度Width: Width = width + padding-left + padding-right + border-left + border-right 布局所占高度Height: Height = height + padding-top + padding-bottom + border-top + border-bottom border-box 布局所占寬度Width: Width = width(包含padding-left + padding-right + border-left + border-right) 布局所占高度Height: Height = height(包含padding-top + padding-bottom + border-top + border-bottom) 邊界塌陷 同一BFC下,相鄰快級元素邊界取最大值 負值作用 display:inline-block是什么呢?相信大家對這個屬性並不陌生,根據名字inline-block我們就可以大概猜出它是結合了inline和block兩者的特性於一身,簡單的說:設置了inline-block屬性的元素既擁有了block元素可以設置width和height的特性,又保持了inline元素不換行的特性。 - window.onload和document.onload是否是同時執行,為什么;
- JS中prototype、proto、super分別是什么?
答: 這個我一臉懵逼,只說了prototype是原型,_proto_是隱式原型。 - arguments是數組嗎?怎么實現用它調用數組方法?類數組和數組的區別是什么?arguments有length屬性嗎? 為什么要遍歷類數組取值組成數組,還有更簡單的方法嗎?
- for…in 和for...of的區別
答:for of 遍歷的是值,for in 遍歷的是索引。 - 數組中的幾個替換/遍歷方法
- 如何理解跨域;
- 跨域你是怎么解決的,jsonp有什么缺點
-> 瀏覽器的同源策略導致了跨域,用於隔離潛在惡意文件的重要安全機制
-> [jsonp ,允許 script加載第三方資源]https://segmentfault.com/a/1190000008445998
-> nginx 代理轉發(nginx 服務內部配置 rewrite proxy_pass)
-> cors 前后端協作設置請求頭部,Access-Control-Allow-Origin 等頭部信息
-> iframe 嵌套通訊,postmessage - cors請求和普通的http請求有什么區別
- 問data-xxx 屬性的作用是什么?
答:data- 屬性賦予我們在所有 HTML 元素上嵌入自定義 data 屬性的能力。 存儲的(自定義)數據能夠被頁面的 JavaScript 中利用,以創建更好的用戶體驗 - promise、setTimeout、async/await的執行順序。
- 用過NodeJS的EventEmitter模塊嗎,它是怎么實現功能的,步驟是什么;
- events模塊只提供了一個對象:events.EventEmitter。EventEmitter的核心就是事件觸發和事件監聽器功能封裝。
- 同源不同標簽之間的通信
- 同源標簽之間如何通信;
- hybrid 實現原理
Hybrid App技術解析 -- 原理篇 - hybrid 通信方式
-> JSBridge
Android的WebView中有一個WebChromeClient類,這個類其實就是用來監聽一些WebView中的事件的,我們發現其中有三個對應於js中的alert(警告框),comfirm(確認框)和prompt(提示框)方法,通過重寫WebView中WebChromeClient類的onJsPrompt()方法來進行js和java的通信。
(1) 在js腳本中把對應的方法名,參數等寫成一個符合協議的uri,並且通過window.prompt方法發送給java層。
(2) 在java層的onJsPrompt方法中接受到對應的message之后,通過JsCallJava類進行具體的解析。
(3) 在JsCallJava類中,我們解析得到對應的方法名,參數等信息,並且在map中查找出對應的類的方法。
React
- React16 有沒有使用過
- react 怎樣提高性能;
答:shouldComponentUpdate: react的每次render都是帶動整個項目一起render的,渲染性能消耗很大很大。要用shouldComponentUpdate更新生命周期函數優化。 當該函數默認返回true的時候,一旦prop或者state有任何變化,都會引起重新render。 shouldComponentUpdate(object nextProps, object nextState) : -boolean 當組件決定任何改變是否要更新到DOM時被調用。作為一個 優化 實現比較this.props 和 nextProps 、this.state 和 nextState ,如果React應該跳過更新,返回false。 當props、state發生變化時,React會根據shouldComponentUpdate方法來決定是否渲染整個組件。 - React 的virtual dom 的了解和jquery的直接操作節點的渲染方式相比的優點;
- React 的生命周期
- componentWillReceiveProps componentShouldUpdate 區別
- componentShouldUpdate 會做setState操作嗎
- React之間組件通信的方式,兩個兄弟組件之間的通信方式
- mobx和redux有沒有了解過
- redux基本組成和設計
- 介紹堆棧和隊列,如何用堆棧實現隊列
VUE
- VUE的原理setter和getter相關知識
- vue項目需要注意什么,可以優化的地方;
- vue的computed實現原理;
- vue-router的原理;
es6 面試題匯總
編程題
- 快速排序
// 時間復雜度(nlogn), 空間復雜度O(n)
var quickSort = function(arr) {
if(arr.length<=1) return arr;
var left = [], right = [], point = Math.floor(arr.length/2);
var middle = arr.splice(point, 1)[0];
for(var i = 0; i < arr.length; i++){
arr[i] < middle ? left.push(arr[i]) : right.push(arr[i]) ;
}
return quickSort(left).concat([middle], quickSort(right));
}
- 數組去重
a.forEach(function(value, index){
b.indexOf(value) === -1 && b.push(value);
})
a.map(function(value, index){
b.indexOf(value) === -1 && b.push(value);
})
var c;
c = a.filter(function(value, index, array){
return index === array.indexOf(value);
})
function unique(arr) {
var ret = [];
var tmp = {};
for(var i = 0, len = arr.length; i < len; i++){
if(!tmp[typeof arr[i] + arr[i]]) {
tmp[typeof arr[i] + arr[i]] = true;
ret.push(arr[i]);
}
}
return ret;
}
- 將多維數組平鋪;
1、 var myNewArray = [].concat.apply([], myArray);
2、 var myNewArray4 = [].concat(...myArray);
3、 var myNewArray = myArray.reduce(function(prev, curr) {
return prev.concat(curr);
});
- 手寫簡易 EventEmiter
// 參照 vue 源碼實現
var EventEmiter = function (){
this._events = {};
};
EventEmiter.prototype.on = function (event, cb){
if (Array.isArray(event)){
for (let i = 0, l = event.length; i < l; i++){
this.on(event[i], cb);
}
} else {
(this._events[event] || (this._events[event] = [])).push(cb);
}
return this;
};
EventEmiter.prototype.once = function (event, cb){
function on () {
this.off(event, cb);
cb.apply(this, arguments);
}
on.fn = cb;
this.on(event, on);
return this;
};
EventEmiter.prototype.off = function (event, cb){
if (!arguments.length){
this._events = Object.create(null);
return this;
}
if (Array.isArray(event)){
for (let i = 0, l = event.length; i < l; i++){
this.off(event[i],cb);
}
return this;
}
if (!cb){
this._events[event] = null;
return this;
}
if (cb){
let cbs = this._events[event];
let i = cbs.length;
while(i--){
if (cb === cbs[i] || cb === cbs[i].fn){
cbs.splice(i, 1);
break;
}
}
return this;
}
};
EventEmiter.prototype.emit = function (event){
let cbs = this._events[event];
let args = Array.prototype.slice.call(arguments, 1);
if (cbs){
for (let i = 0, l = cbs.length; i < l; i++){
cbs[i].apply(this,args);
}
}
};
- 寫一個url解析函數,解析出查詢參數;
function parseUrl(url){
var result = [];
var query = url.split("?")[1];
var queryArr = query.split("&");
queryArr.forEach(function(item){
var obj = {};
var value = item.split("=")[1];
var key = item.split("=")[0];
obj[key] = value;
result.push(obj);
});
return result;
}
- ['1.45.0','1.5','6','3.3.3.3']要求從小到大排序,注意'1.45'比'1.5'大;
// 使用的是選擇排序
const versionSort = version => {
const temp = version.map(v => v.split('.'));
for (let i = 0; i < temp.length; i++) {
let minIndex = i;
for (let j = i; j < temp.length; j++) {
for (let k = 0; k < temp[j].length; k++) {
const current = +temp[j][k],
min = +temp[minIndex][k];
if (current < min) {
minIndex = j;
}
// 只要不等,就立刻結束最內層遍歷!
if (current !== min) {
break
}
}
}
[temp[i], temp[minIndex]] = [temp[minIndex], temp[i]];
}
return temp.map(v = > v.join('.'))
};
-
隨意給定一個無序的、不重復的數組arr,任意抽取n個數,相加和為sum,也可能無解,請寫出該函數。
-
節流函數怎么寫;
function debounce(fn, interval, immediate) {
let timer;
return function() {
const context = this;
const args = arguments;
timer && clearTimeout(timer);
if(immediate) {
var callNow = !timer;
timer = setTimeout(function() {
timer = null;
}, interval);
callNow && fn.apply(context, args);
} else {
timer = setTimeout(function() {
fn.apply(context, args);
}, interval);
}
}
}
- 手寫bind函數;
Function.prototype.bind = function(ctx) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var F = function() {};
var fBind = function() {
var argsBind = Array.prototype.slice.call(arguments);
return self.apply(this instanceof F ? this : ctx, args.concat(argsBind));
}
F.prototype = this.prototype;
fBind.prototype = new F();
return fBind;
}
-
promise封裝;
簡單的 Promise -
寫一個parseInt函數;
function parseInt(s, radix = 10) {
if (typeof s !== 'string') {
return NaN;
}
if (typeof radix !== 'number' || radix < 2 || radix > 36) {
return NaN;
}
let result = 0;
for (let i = 0; i < s.length; i += 1) {
let c = s.charCodeAt(i);
// 小寫大寫字母轉換為數字
if (c >= 97) {
c -= 87; // - 'a' + 10
} else if (c >= 65) {
c -= 55; // - 'A' + 10
} else {
c -= 48; // - '0'
}
// 如果字母轉化后的值大於進制數,則跳出循環返回之前的結果
if (c >= radix) {
if (i === 0) {
return NaN;
}
break;
}
// 結果累加,和進制相關
result = (result * radix) + c;
}
return result;
}
- 正則表達式實現1000000中間加',';
function comma(num) {
var source = String(num).split(".");
source[0] = source[0].replace(new RegExp('(\\d)(?=(\\d{3})+$)','ig'),"$1,");
return source.join(".");
}
-
請使用數組的reduce方法實現數組的map方法;
-
大數相加
function sumStrings(a,b) {
while(a.length < b.length){
a = "0" + a;
}
while(b.length < a.length){
b = "0" + b;
}
var addOne = 0;
var result = [];
for(var i=a.length-1;i>=0;i--){
var c1 = a.charAt(i) - 0;
var c2 = b.charAt(i) - 0;
var sum = c1 + c2 + addOne;
if(sum > 9){
result.unshift(sum - 10);
addOne = 1;
}
else{
result.unshift(sum);
addOne = 0;
}
}
if(addOne){
result.unshift(addOne);
}
if(!result[0]){
result.splice(0,1);
}
return result.join("");
}
- 請用至少兩種方法判斷一個對象是否是數組,如何將非數組轉化為數組
a instanceof Array;
a.constructor === Array;
a.__proto__ === Array.prototype;
Array.prototype.isPrototypeOf(a); // isProtoTypeOf()
Object.getPrototypeOf(a) === Array.prototype; // Object.getPrototypeOf()
Object.prototype.toString.call(a) === '[object Array]'; // 首推 -> 前幾種繼承會擾亂, iframe 下 instance 失效
Array.isArray() // polyfill 就是調用字符串判斷法
var argsArray = Array.prototype.slice.call(arguments);
安全
-
xss和csrf攻擊;
-> xss 跨站腳本攻擊,主要是前端層面的,用戶在輸入層面插入攻擊腳本,改變頁面的顯示,或則竊取網站 cookie,預防方法:不相信用戶的所有操作,對用戶輸入進行一個轉義,不允許 js 對 cookie 的讀寫
-> csrf 跨站請求偽造,以你的名義,發送惡意請求,通過 cookie 加參數等形式過濾
我們沒法徹底杜絕攻擊,只能提高攻擊門檻 -
cookie的有哪些安全的設置;
