1、如何使元素垂直水平居中?
答:
a、知道具體寬高:
父級定位,子級定位,寬高300px
.container {
position: absolute;
left: calc(50% - 150px);
top: calc(50% - 150px);
width: 300px;
height: 300px;
border: 1px solid red;
}
或者
.container {
position: absolute;
left: calc(50% - 150px);
top: calc(50% - 150px);
width: 300px;
height: 300px;
border: 1px solid red;
}
b、不知道具體寬高:
.container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); // 自身寬度和高度的一半
border: 1px solid red;
}
或者單位vh
.container {
width: 300px;
margin: 50vh auto 0;
transform: translateY(-50%);
border: 1px solid red;
}
C、Flex
.container {
display: flex;
height: 100px;
}
.inner {
margin: auto;
}
或者
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
D、Table
.container {
display: table; /* 讓div以表格的形式渲染 */
width: 100%;
border: 1px solid red;
}
.inner {
display: table-cell; /* 讓子元素以表格的單元格形式渲染 */
text-align: center;
vertical-align: middle;
}
2、如何實現佈局左邊固定寬度右邊自適應?答:
a
.left{
width:200px;
float:left;
background:red;
}
.right{
overflow:hidden;
background:blue;
}
B、
.container{
display:flex;/*設爲伸縮容器*/
}
.left{
width:200px;
border: 2px solid blue;
background:red;
}
.right{
border: 2px solid yellow;
flex:1;/*這裏設置爲佔比1,填充滿剩餘空間*/
background:blue;
}
3、用到了關於h5的哪些新特性?
答:
· 新增選擇器 document.querySelector、document.querySelectorAll
· 拖拽釋放(Drag and drop) API
· 媒體播放的 video 和 audio
· 本地存儲 localStorage 和 sessionStorage
· 離線應用 manifest
· 桌面通知 Notifications
· 語意化標籤 article、footer、header、nav、section
· 增強表單控件 calendar、date、time、email、url、search
· 地理位置 Geolocation
· 多任務 webworker
· 全雙工通信協議 websocket
· 歷史管理 history
· 跨域資源共享(CORS) Access-Control-Allow-Origin
· 頁面可見性改變事件 visibilitychange
· 跨窗口通信 PostMessage
· Form Data 對象
· 繪畫 canvas
4、有哪些常用的瀏覽器對象方法?
答:window對象
History 對象
Location
Navigator
5、用什麼方法區分移動端還是pc端或者是微信app還是自己的官方app?
答:window.navigator.userAgent來匹配對應字段;
6、文本超出部分省略號怎麼寫?
答:width:固定;height:100px;overflow:hidden;white-space:no-wrap;text-overflow:ellipsis;
7、怎麼樣從web前端方面優化性能?至少列舉5點?
答:https://blog.csdn.net/weixin_39141802/article/details/81015569
減少http請求,合理設置 HTTP緩存、使用瀏覽器緩存、啓用壓縮、CSS Sprites、LazyLoad Images、CSS放在頁面最上部,javascript放在頁面最下面、減少cookie傳輸、Javascript代碼優化、CSS選擇符優化、CDN加速
8、常用的數據類型有哪些?哪些是值類型哪些是引用類型?
答:
a、基本數據類型和引用數據類型
ECMAScript包括兩個不同類型的值:基本數據類型和引用數據類型。
基本數據類型指的是簡單的數據段,引用數據類型指的是有多個值構成的對象。
當我們把變量賦值給一個變量時,解析器首先要確認的就是這個值是基本類型值還是引用類型值。
b、常見的基本數據類型:
Number、String 、Boolean、Null和Undefined。基本數據類型是按值訪問的,因爲可以直接操作保存在變量中的實際值。示例:
var a = 10;
var b = a;
b = 20;
console.log(a); // 10值
上面,b獲取的是a值得一份拷貝,雖然,兩個變量的值相等,但是兩個變量保存了兩個不同的基本數據類型值。
b只是保存了a複製的一個副本。所以,b的改變,對a沒有影響。
下圖演示了這種基本數據類型賦值的過程:
c、引用類型數據:
也就是對象類型Object type,比如:Object 、Array 、Function 、Data等。
javascript的引用數據類型是保存在堆內存中的對象。
與其他語言的不同是,你不可以直接訪問堆內存空間中的位置和操作堆內存空間。只能操作對象在棧內存中的引用地址。
所以,引用類型數據在棧內存中保存的實際上是對象在堆內存中的引用地址。通過這個引用地址可以快速查找到保存中堆內存中的對象。
var obj1 = new Object();
var obj2 = obj1;
obj2.name = "我有名字了";
console.log(obj1.name); // 我有名字了
說明這兩個引用數據類型指向了同一個堆內存對象。obj1賦值給onj2,實際上這個堆內存對象在棧內存的引用地址複製了一份給了obj2,
但是實際上他們共同指向了同一個堆內存對象。實際上改變的是堆內存對象。
下面我們來演示這個引用數據類型賦值過程:
d、總結區別
a 聲明變量時不同的內存分配:
1)原始值:存儲在棧(stack)中的簡單數據段,也就是說,它們的值直接存儲在變量訪問的位置。
這是因爲這些原始類型佔據的空間是固定的,所以可將他們存儲在較小的內存區域 – 棧中。這樣存儲便於迅速查尋變量的值。
2)引用值:存儲在堆(heap)中的對象,也就是說,存儲在變量處的值是一個指針(point),指向存儲對象的內存地址。
這是因爲:引用值的大小會改變,所以不能把它放在棧中,否則會降低變量查尋的速度。相反,放在變量的棧空間中的值是該對象存儲在堆中的地址。
地址的大小是固定的,所以把它存儲在棧中對變量性能無任何負面影響。
b 不同的內存分配機制也帶來了不同的訪問機制
1)在javascript中是不允許直接訪問保存在堆內存中的對象的,所以在訪問一個對象時,
首先得到的是這個對象在堆內存中的地址,然後再按照這個地址去獲得這個對象中的值,這就是傳說中的按引用訪問。
2)而原始類型的值則是可以直接訪問到的。
c 複製變量時的不同
1)原始值:在將一個保存着原始值的變量複製給另一個變量時,會將原始值的副本賦值給新變量,此後這兩個變量是完全獨立的,他們只是擁有相同的value而已。
2)引用值:在將一個保存着對象內存地址的變量複製給另一個變量時,會把這個內存地址賦值給新變量,
也就是說這兩個變量都指向了堆內存中的同一個對象,他們中任何一個作出的改變都會反映在另一個身上。
(這裏要理解的一點就是,複製對象時並不會在堆內存中新生成一個一模一樣的對象,只是多了一個保存指向這個對象指針的變量罷了)。多了一個指針
d 參數傳遞的不同(把實參複製給形參的過程)
首先我們應該明確一點:ECMAScript中所有函數的參數都是按值來傳遞的。
但是爲什麼涉及到原始類型與引用類型的值時仍然有區別呢?還不就是因爲內存分配時的差別。
1)原始值:只是把變量裏的值傳遞給參數,之後參數和這個變量互不影響。
2)引用值:對象變量它裏面的值是這個對象在堆內存中的內存地址,這一點你要時刻銘記在心!
因此它傳遞的值也就是這個內存地址,這也就是爲什麼函數內部對這個參數的修改會體現在外部的原因了,因爲它們都指向同一個對象。
9、常用的數組操作的方法有哪些?
答:forEach()、sort()、reverse()、push()、unshift()、splice()、pop()、shift()、concat()、indexOf();join()
10、寫一個數組去重的方法?
答:a、利用對象屬性
Array.prototype.distinct = function (){
var arr = this,
i,
obj = {},
result = [],
len = arr.length;
for(i = 0; i< arr.length; i++){
if(!obj[arr[i]]){ //如果能查找到,證明數組元素重複了
obj[arr[i]] = 1;
result.push(arr[i]);
}
}
return result;
};
var a = [1,2,3,4,5,6,5,3,2,4,56,4,1,2,1,1,1,1,1,1,];
var b = a.distinct();
console.log(b.toString());
b、indexof
Array.prototype.distinct = function (){
var arr = this,
result = [],
len = arr.length;
arr.forEach(function(v, i ,arr){ //這裏利用map,filter方法也可以實現
var bool = arr.indexOf(v,i+1); //從傳入參數的下一個索引值開始尋找是否存在重複
if(bool === -1){
result.push(v);
}
})
return result;
};
var a = [1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,2,3,3,2,2,1,23,1,23,2,3,2,3,2,3];
var b = a.distinct();
console.log(b.toString());
C、es6:let resultarr = [...new Set(arr)];
11、寫一個面向對象的例子
答: function Cat(name,color){
this.name = name;
this.color = color;
}
Cat.prototype.type = "貓科動物";
Cat.prototype.eat = function(){alert("吃老鼠")};
var cat1 = new Cat("大毛","黃色");
var cat2 = new Cat("二毛","黑色");
12、es6中常用到的方法和特性
答:
A、定義函數
es6寫法:
var human = {
breathe(name) { //不需要function也能定義breathe函數。
console.log(name + ' is breathing...');
}};human.breathe('jarson'); //輸出 ‘jarson is breathing...’
轉成js代碼:
var human = {
breathe: function(name) {
console.log(name + 'is breathing...');
}};human.breathe('jarson');
B、創建類
我們知道,javascript不像java是面向對象編程的語言,而只可以說是基於對象編程的語言。所以在js中,我們通常都是用function和prototype來模擬類這個概念。
但是現在有了es6,我們可以像java那樣‘明目張膽’的創建一個類了:
class Human {
constructor(name) {
this.name = name;
}
breathe() {
console.log(this.name + " is breathing");
}} var man = new Human("jarson");man.breathe(); //jarson is breathing
上面代碼轉爲js格式:
function Human(name) {
this.name = name;
this.breathe = function() {
console.log(this.name + ' is breathing');
}}var man = new Human('jarson');man.breathe(); //jarson is breathing
所以我們看到,我們可以像java那樣語義化的去創建一個類。另外,js中的繼承父類,需要用prototype來實現。那麼在es6中,又有什麼新的方法來實現類的繼承呢?繼續看:
假如我們要創建一個Man類繼承上面的Human類,es6代碼:
class Man extends Human {
constructor(name, sex) {
super(name);
this.sex = sex;
}
info(){
console.log(this.name + 'is ' + this.sex);
}}var xx = new Man('jarson', 'boy');xx.breathe(); //jarson is breathingxx.info(); //arsonis boy
代碼很簡單,不作贅述,可以使用文章裏提到的在線工具去試試效果就能明白了。需要注意的是:super()是父類的構造函數。
模塊
在ES6標準中,javascript原生支持module了。將不同功能的代碼分別寫在不同文件中,各模塊只需導出(export)公共接口部分,然後在需要使用的地方通過模塊的導入(import)就可以了。下面繼續看例子:
內聯導出
ES6模塊裏的對象可在創建它們的聲明中直接導出,一個模塊中可無數次使用export。
先看模塊文件app.js:
export class Human{
constructor(name) {
this.name = name;
}
breathe() {
console.log(this.name + " is breathing");
} } export function run(){
console.log('i am runing'); }function eat() {
console.log('i am eating');}
例子中的模塊導出了兩個對象:Human類和run函數, eat函數沒有導出,則仍爲此模塊私有,不能被其他文件使用。
導出一組對象
另外,其實如果需要導出的對象很多的時候,我們可以在最後統一導出一組對象。
更改app.js文件:
class Human{
constructor(name) {
this.name = name;
}
breathe() {
console.log(this.name + " is breathing");
} } function run(){
console.log('i am runing'); }function eat() {
console.log('i am eating');}export {Human, run};
這樣的寫法功能和上面一樣,而且也很明顯,在最後可以清晰的看到導出了哪些對象。
C、Default導出
導出時使用關鍵字default,可將對象標註爲default對象導出。default關鍵字在每一個模塊中只能使用一次。它既可以用於內聯導出,也可以用於一組對象導出聲明中。
查看導出default對象的語法:
... //創建類、函數等等export default { //把Human類和run函數標註爲default對象導出。
Human,
run };
無對象導入
如果模塊包含一些邏輯要執行,且不會導出任何對象,此類對象也可以被導入到另一模塊中,導入之後只執行邏輯。如:
import './module1.js';
導入默認對象
使用Default導出方式導出對象,該對象在import聲明中將直接被分配給某個引用,如下例中的“app”。
import app from './module1.js';
上面例子中,默認./module1.js文件只導出了一個對象;若導出了一組對象,則應該在導入聲明中一一列出這些對象,如:
import {Human, run} from './app.js'
D、let與const
在我看來,在es6新特性中,在定義變量的時候統統使用let來代替var就好了,const則很直觀,用來定義常量,即無法被更改值的變量。
for (let i=0;i<2;i++) {
console.log(i); //輸出: 0,1}
E、箭頭函數
ES6中新增的箭頭操作符=>簡化了函數的書寫。操作符左邊爲輸入的參數,而右邊則是進行的操作以及返回的值,這樣的寫法可以爲我們減少大量的代碼,看下面的實例:
let arr = [6, 8, 10, 20, 15, 9];arr.forEach((item, i) => console.log(item, i));let newArr = arr.filter((item) => (item<10));console.log(newArr); //[6, 8, 9];
上面的(item, i)就是參數,後面的console.log(item, i)就是回到函數要執行的操作邏輯。
上面代碼轉爲js格式:
var arr = [6, 8, 10, 20, 15, 9];arr.forEach(function(item, i) {
return console.log(item, i);});var newArr = arr.filter(function(item) {
return (item < 10);});console.log(newArr);
F、字符串模版
ES6中允許使用反引號 ` 來創建字符串,此種方法創建的字符串裏面可以包含由美元符號加花括號包裹的變量${vraible}。看一下實例就會明白了:
//產生一個隨機數let num = Math.random();//將這個數字輸出到consoleconsole.log(`your num is ${num}`);
H、解構
若一個函數要返回多個值,常規的做法是返回一個對象,將每個值做爲這個對象的屬性返回。在ES6中,利用解構這一特性,可以直接返回一個數組,然後數組中的值會自動被解析到對應接收該值的變量中。我們來看例子:
function getVal() {
return [1, 2];}var [x,y] = getVal(); //函數返回值的解構console.log('x:'+x+', y:'+y); //輸出:x:1, y:2
I、默認參數
現在可以在定義函數的時候指定參數的默認值了,而不用像以前那樣通過邏輯或操作符來達到目的了。
function sayHello(name){
var name=name||'tom'; //傳統的指定默認參數的方式
console.log('Hello '+name);}//運用ES6的默認參數function sayHello2(name='tom'){ //如果沒有傳這個參數,纔會有默認值,
console.log(`Hello ${name}`);}sayHello();//輸出:Hello tomsayHello('jarson');//輸出:Hello jarsonsayHello2();//輸出:Hello tomsayHello2('jarson');//輸出:Hello jarson
注意: sayHello2(name='tom')這裏的等號,意思是沒有傳這個參數,則設置默認值,而不是給參數賦值的意思。
13、幾種常用的數據存儲的方式,優缺點
答:
瀏覽器的緩存機制提供了可以將用戶數據存儲在客戶端上的方式,可以利用cookie,session等跟服務端進行數據交互。
一、cookie和session
cookie和session都是用來跟蹤瀏覽器用戶身份的會話方式。
區別:
1、保持狀態:cookie保存在瀏覽器端,session保存在服務器端
2、使用方式:
(1)cookie機制:如果不在瀏覽器中設置過期時間,cookie被保存在內存中,生命週期隨瀏覽器的關閉而結束,這種cookie簡稱會話cookie。如果在瀏覽器中設置了cookie的過期時間,cookie被保存在硬盤中,關閉瀏覽器後,cookie數據仍然存在,直到過期時間結束才消失。
Cookie是服務器發給客戶端的特殊信息,cookie是以文本的方式保存在客戶端,每次請求時都帶上它
(2)session機制:當服務器收到請求需要創建session對象時,首先會檢查客戶端請求中是否包含sessionid。如果有sessionid,服務器將根據該id返回對應session對象。如果客戶端請求中沒有sessionid,服務器會創建新的session對象,並把sessionid在本次響應中返回給客戶端。通常使用cookie方式存儲sessionid到客戶端,在交互中瀏覽器按照規則將sessionid發送給服務器。如果用戶禁用cookie,則要使用URL重寫,可以通過response.encodeURL(url) 進行實現;API對encodeURL的結束爲,當瀏覽器支持Cookie時,url不做任何處理;當瀏覽器不支持Cookie的時候,將會重寫URL將SessionID拼接到訪問地址後。
3、存儲內容:cookie只能保存字符串類型,以文本的方式;session通過類似與Hashtable的數據結構來保存,能支持任何類型的對象(session中可含有多個對象)
4、存儲的大小:cookie:單個cookie保存的數據不能超過4kb;session大小沒有限制。
5、安全性:cookie:針對cookie所存在的攻擊:Cookie欺騙,Cookie截獲;session的安全性大於cookie。
原因如下:(1)sessionID存儲在cookie中,若要攻破session首先要攻破cookie;
(2)sessionID是要有人登錄,或者啓動session_start纔會有,所以攻破cookie也不一定能得到sessionID;
(3)第二次啓動session_start後,前一次的sessionID就是失效了,session過期後,sessionID也隨之失效。
(4)sessionID是加密的
(5)綜上所述,攻擊者必須在短時間內攻破加密的sessionID,這很難。
6、應用場景:
cookie:(1)判斷用戶是否登陸過網站,以便下次登錄時能夠實現自動登錄(或者記住密碼)。如果我們刪除cookie,則每次登錄必須從新填寫登錄的相關信息。
(2)保存上次登錄的時間等信息。
(3)保存上次查看的頁面
(4)瀏覽計數
session:Session用於保存每個用戶的專用信息,變量的值保存在服務器端,通過SessionID來區分不同的客戶。
(1)網上商城中的購物車
(2)保存用戶登錄信息
(3)將某些數據放入session中,供同一用戶的不同頁面使用
(4)防止用戶非法登錄
7、缺點:cookie:(1)大小受限
(2)用戶可以操作(禁用)cookie,使功能受限
(3)安全性較低
(4)有些狀態不可能保存在客戶端。
(5)每次訪問都要傳送cookie給服務器,浪費帶寬。
(6)cookie數據有路徑(path)的概念,可以限制cookie只屬於某個路徑下。
session:(1)Session保存的東西越多,就越佔用服務器內存,對於用戶在線人數較多的網站,服務器的內存壓力會比較大。
(2)依賴於cookie(sessionID保存在cookie),如果禁用cookie,則要使用URL重寫,不安全
(3)創建Session變量有很大的隨意性,可隨時調用,不需要開發者做精確地處理,所以,過度使用session變量將會導致代碼不可讀而且不好維護。
二、WebStorage
WebStorage的目的是克服由cookie所帶來的一些限制,當數據需要被嚴格控制在客戶端時,不需要持續的將數據發回服務器。
WebStorage兩個主要目標:(1)提供一種在cookie之外存儲會話數據的路徑。(2)提供一種存儲大量可以跨會話存在的數據的機制。
HTML5的WebStorage提供了兩種API:localStorage(本地存儲)和sessionStorage(會話存儲)。
1、生命週期:localStorage:localStorage的生命週期是永久的,關閉頁面或瀏覽器之後localStorage中的數據也不會消失。localStorage除非主動刪除數據,否則數據永遠不會消失。
sessionStorage的生命週期是在僅在當前會話下有效。sessionStorage引入了一個“瀏覽器窗口”的概念,sessionStorage是在同源的窗口中始終存在的數據。只要這個瀏覽器窗口沒有關閉,即使刷新頁面或者進入同源另一個頁面,數據依然存在。但是sessionStorage在關閉了瀏覽器窗口後就會被銷燬。同時獨立的打開同一個窗口同一個頁面,sessionStorage也是不一樣的。
2、存儲大小:localStorage和sessionStorage的存儲數據大小一般都是:5MB
3、存儲位置:localStorage和sessionStorage都保存在客戶端,不與服務器進行交互通信。
4、存儲內容類型:localStorage和sessionStorage只能存儲字符串類型,對於複雜的對象可以使用ECMAScript提供的JSON對象的stringify和parse來處理
5、獲取方式:localStorage:window.localStorage;;sessionStorage:window.sessionStorage;。
6、應用場景:localStoragese:常用於長期登錄(+判斷用戶是否已登錄),適合長期保存在本地的數據。sessionStorage:敏感賬號一次性登錄;
WebStorage的優點:
(1)存儲空間更大:cookie爲4KB,而WebStorage是5MB;
(2)節省網絡流量:WebStorage不會傳送到服務器,存儲在本地的數據可以直接獲取,也不會像cookie一樣美詞請求都會傳送到服務器,所以減少了客戶端和服務器端的交互,節省了網絡流量;
(3)對於那種只需要在用戶瀏覽一組頁面期間保存而關閉瀏覽器後就可以丟棄的數據,sessionStorage會非常方便;
(4)快速顯示:有的數據存儲在WebStorage上,再加上瀏覽器本身的緩存。獲取數據時可以從本地獲取會比從服務器端獲取快得多,所以速度更快;
(5)安全性:WebStorage不會隨着HTTP header發送到服務器端,所以安全性相對於cookie來說比較高一些,不會擔心截獲,但是仍然存在僞造問題;
(6)WebStorage提供了一些方法,數據操作比cookie方便;
setItem (key, value) —— 保存數據,以鍵值對的方式儲存信息。
getItem (key) —— 獲取數據,將鍵值傳入,即可獲取到對應的value值。
removeItem (key) —— 刪除單個數據,根據鍵值移除對應的信息。
clear () —— 刪除所有的數據
key (index) —— 獲取某個索引的key
14、localstorage設置過期時間?
答:
function set(key,value){
var curTime = new Date().getTime();
localStorage.setItem(key,JSON.stringify({data:value,time:curTime}));
}
function get(key,exp){
var data = localStorage.getItem(key);
var dataObj = JSON.parse(data);
if (new Date().getTime() - dataObj.time>exp) {
localStorage.removeItem(key);
}else{
var dataObjDatatoJson = JSON.parse(dataObj.data)
return dataObjDatatoJson;
}
}