一、元素上下垂直居中的方式有哪些?
元素水平垂直居中的方式有哪些?
absolute加margin方案
fixed 加 margin 方案
display:table 方案
行內元素line-height方案
flex 彈性佈局方案
transform 未知元素寬高解決方案
absolute加margin方案
div{
position: absolute;
width: 100px;
height: 100px;
left: 50%;
top: 50%:
margin-top: -50px;
margin-left: -50px;
}
fixed 加 margin 方案
div{
position: fixed;
width: 100px;
height: 100px;
top: 0;
right:0;
left: 0;
bottom: 0;
margin: auto;
}
display:table 方案
div{
display: table-cell;
vertical-align: middle;
text-align: center;
width: 100px;
height: 100px;
}
行內元素line-height方案
div{
text-align: center;
line-height: 100px;
}
flex 彈性佈局方案
div{
display: flex;
align-items: center;
justify-content:center
}
transform 未知元素寬高解決方案
div{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%)
}
二、var let const的區別及使用場景?
首先3個都是js聲明變量所用
Var
var 所聲明的變量,做用域爲該語句所在的函數內,且存在變量提高
console.log(a) // 變量提高,var a 被提至所在做用域頂部, 因此這裏輸出的值爲 undefined
var a = 'JS'
for (var i = 0; i <10; i++) {
setTimeout(function() { // 同步註冊回調函數到 異步的 宏任務隊列。
console.log(i); // 執行此代碼時,同步代碼for循環已經執行完成
}, 0);
}
10 ... 10 // 10個10
console.log(i) // i 做用域全局 輸出10
後面聲明的會覆蓋以前聲明的變量
var a = 'JS'
var a = 'JavaScript'
Let
let 所聲明的變量,做用域爲該語句的代碼塊內,不存在變量提高
console.log(a) // 變量沒有被提高, 輸出 ReferenceError: a is not defined
let a = 'JavaScript'
for (let i = 0; i <10; i++) {
setTimeout(function() { // 同步註冊回調函數到 異步的 宏任務隊列。
console.log(i); // 執行此代碼時,同步代碼for循環已經執行完成
}, 0);
}
1...10 // 1到10
console.log(i) // i做用域for 塊級內,輸出 i is not defined
不容許重複聲明
let a = 'JavaScript'
let a = 'JS' // 'a' has already been declared
Const
const 包含let 全部特性, 區別是const聲明的變量是一個只讀的不可修改的
這裏注意,const保證的不是所聲明的值不得改動, 而是變量指向的內存不可改動
代碼示例
const a = {
content: 'JavaScript'
}
a.content = 'JS' // JS
a = {
content: 'JS' // 這裏改變了內存, 因此報錯 Assignment to constant variable
}
三句話總結
使用var聲明的變量,其做用域爲該語句所在的函數內,且存在變量提高現象,後面的覆蓋前面的
使用let聲明的變量,其做用域爲該語句所在的代碼塊內,不存在變量提高, 不能重複聲明
使用const聲明的是常量,在後面出現的代碼中不能再修改該常量的內存
三、如何理解es6中的類?
首先,JS做爲一門非面嚮對象語言,在es6以前,並無提供對類的支持,咱們經常使用的作法是經過構造函數來模擬類的實現, 經過將屬性及方法定義在原型上共享給其實例
簡單實現:
function JS(name) {
this.name = name
}
JS.prototype.getName = function(){
console.log(this.name)
}
const child = new JS('測試')
ES6 中的Class
es6中的class只是一個語法糖,class的寫法只是讓對象原型看起來更加清晰
簡單使用:
class JS {
constructor(name) {
this.name = name
}
getName() {
console.log(
this.name
)
}
}
const child = new JS('測試')
每一個類中都有一個constructor方法,若是沒有顯示定義, 會默認添加一個空的constructor,等同於ES5中的構造函數, 類的全部方法都是定義在類的prototype屬性上面,兩者的主要區別在於Class必須使用new調用, ES5中構造函數不使用new也能夠調用, class 中新增靜態方法(static)關鍵字, 靜態方法不能被繼承只有經過類自己來調用
class JS {
constructor(name) {
this.name = name
}
static
getName() {
// static 方法只有類自己能調用,實例不能繼承
console.log(this.name)
}
}
Extends 繼承
class 也能夠經過extends 關鍵字實現繼承
代碼示例:
class JS {
constructor(name) {
this.name = name
}
getName() {
console.log(this.name)
}
}
class Css extends Js{
constructor() {
super();
}
}
const child = new Css('測試')
child.getName()
// '測試'
extends 注意點
使用extends 繼承時,子類構造函數中必須調用super(), 表明調用父類的構造函數
super雖然代碼父類的constructor,可是返回的子類的實例
super做爲函數調用時,表明類的構造函數
super做爲對象調用時, 在普通方法中,指向父類的原型對象, 靜態方法中指向父類
四、如何理解es6中的Promise?
js是單線程的,也就是說一次只能完成一個任務,爲了解決這個問題,js將任務的執行模式分爲兩種, 同步和異步, 在es5中咱們處理異步只能經過的回調的方式進行處理,在多層異步中,回調會一層一層嵌套,也就是所謂的回調地獄,promise就是異步編程的一種解決方案
Promise
特色:
對象的狀態不受外界影響, promise對象表明一個異步操做,有三種狀態pendding(進行中), fulfilled(成功), rejected(失敗)
一旦狀態改變,就不會再變, 狀態的改變只有兩種可能, pendding => fulfilled及pendding => rejected
基本用法:
const promise = new Promise(
function(resolve,reject){
// ... some code
if(/* 異步操做成功 */){
resolve(value);
// 將狀態從pendding變成fulfilled
}else{
reject(error);
// 將狀態從pendding變成rejected
}
}
);
promise 生成實例後可使用then方法接收resolved狀態和rejected狀態的回調函數
promise.then(()=>{
console.log('resolved')
},()=>{
console.log('rejected')
})
promise原型上具備catch方法, catch方法是rejection的別名, 用於指定發生錯誤時的回調函數
promise.then(()=>{
console.log('resolved')
},()=>{
console.log('rejected')
}).catch((err)=>{
console.log('catch')
})
promise原型上具備finally方法,用於無論promise對象最後的狀態如何,都會執行的操做
promise.then(()=>{
console.log('resolved')
},()=>{
console.log('rejected')
}).finally((err)=>{
console.log('end')
})
Promise.all
Promise.all方法用於將多個 Promise 實例,包裝成一個新的 Promise 實例
簡單使用:
const p = Promise.all([p1,p2,p3]);
特色:
參數都是promise實例,若是不是會調用promise.resolve方法將其轉爲promise實例
p的獎態由傳入的promise實例的狀態決定
promise實例狀態都變成fulfilled,p狀態爲fulfilled
promise實例狀態一個變成rejected,p狀態爲rejected
六、如何理解es6中的Proxy?
如何理解es6中的Proxy?
試題解析:對proxy的理解,可能會延伸到vue的雙向綁定
Proxy(代理) 定義
能夠理解爲爲目標對象架設一層攔截,外界對該對象的訪問,都必須經過這層攔截
簡單示例:
const obj = new Proxy({}, {
get: (target, key, receiver) => {
return 'JS'
console.log(`get ${key}`)
},
set: (target, key, value, receiver) => {
console.log(`set ${key}`)
},
})
obj.name = 'JS'
// set name
// JS
obj.name
// 這裏進入get的回調函數,全部直接返回 JS
從上面的示例中能夠看出,Proxy存在一種機制,能夠對外界的讀寫操做進行改寫
Proxy 實例方法
proxy除了代理get,set操做,還能代理其它的操做,以下
handler.getPrototypeOf()
// 在讀取代理對象的原型時觸發該操做,好比在執行 Object.getPrototypeOf(proxy) 時。
handler.setPrototypeOf()
// 在設置代理對象的原型時觸發該操做,好比在執行 Object.setPrototypeOf(proxy, null) 時。
handler.isExtensible()
// 在判斷一個代理對象是不是可擴展時觸發該操做,好比在執行 Object.isExtensible(proxy) 時。
handler.preventExtensions()
// 在讓一個代理對象不可擴展時觸發該操做,好比在執行 Object.preventExtensions(proxy) 時。
handler.getOwnPropertyDescriptor()
// 在獲取代理對象某個屬性的屬性描述時觸發該操做,好比在執行 Object.getOwnPropertyDescriptor(proxy, "foo") 時。
handler.defineProperty()
// 在定義代理對象某個屬性時的屬性描述時觸發該操做,好比在執行 Object.defineProperty(proxy, "foo", {}) 時。
handler.has()
// 在判斷代理對象是否擁有某個屬性時觸發該操做,好比在執行 "foo" in proxy 時。
handler.
get
()
// 在讀取代理對象的某個屬性時觸發該操做,好比在執行 proxy.foo 時。
handler.set()
// 在給代理對象的某個屬性賦值時觸發該操做,好比在執行 proxy.foo = 1 時。
handler.deleteProperty()
// 在刪除代理對象的某個屬性時觸發該操做,好比在執行 delete proxy.foo 時。
handler.ownKeys()
// 在獲取代理對象的全部屬性鍵時觸發該操做,好比在執行 Object.getOwnPropertyNames(proxy) 時。
handler.apply()
// 在調用一個目標對象爲函數的代理對象時觸發該操做,好比在執行 proxy() 時。
handler.construct()
// 在給一個目標對象爲構造函數的代理對象構造實例時觸發該操做,好比在執行new proxy() 時。
爲何要使用Proxy
攔截和監視外部對對象的訪問
下降函數或類的複雜度
在複雜操做前對操做進行校驗或對所需資源進行管理
七、如何理解es6中的decorator?
Decorator是ES7中的提案,概念借鑑於python, 它做用於一個目標類爲其添加屬性於方法
咱們用一個比喻來理解Decorator, 把孫悟空當作是一個類,那麼棒子就是裝飾器爲其裝備的武器
代碼理解:
@stick class Monkey{
}
function stick(target){// 第一個參數就是目標類的自己
target.ATK = 100000
}
Monkey.ATK
// 爲悟空裝備了棒子,攻擊力提升了100000
// 若是一個參數不夠用,能夠在裝飾器外層再包一層
function stick(atk){
return function(targt){
target.ATK = atk
}
}
@stick(200000)
// 這樣咱們就爲悟空增長了200000攻擊力
class Monkey{
}
Decorator 不只能修飾類,也能修飾類的方法
class Monkey{
@setName name(){
this.name = '孫悟空'
}
}
Decorator 只能修飾類及類的方法,不能修飾於函數,由於存在函數提高
Mixin
在修飾器基礎上,咱們能夠實現mixin(混入),意思在一個對象中混入另外一個對象的方法
代碼示例:
export function mixins(...list){
return function(target){
Object.assign(target.prototype,...list)
}
}
const skill = {
shapeshifting(){
console.log('72變')
}
}
@mixins(skill)
class Monkey{
}
Object.assign(Monkey.prototype, skill)
const swk = new Monkey()
swk.shapeshifting()
// 72變
使用Decorator的好處
擴展功能,相對於繼承增長了更多的靈活性
代碼可讀性更高,裝飾器正確命名至關於註釋
八、Es6中新增的數據類型有哪些?使用場景?
Es6中新增的數據類型有哪些?使用場景?
es6中新增一種原始數據類型Symbol,最大的特色是惟一性,Symbol值經過Symbol函數生成, 在es5中對象的屬性都是字符串,咱們使用他人定義的對象,而後去新增本身的屬性,這樣容易起衝突覆蓋原有的屬性, Symbol也能夠當作爲一個字符串,不過這個字符能保證是獨一無二的
基本示例:
// Object
const obj = {
name:'JS'
}
obj.name ='JS每日一題'
// Symbol
const name = Symbol('name')
// 這裏的參數沒有特殊意義,能夠當作爲Symbol加了一個標記
obj[name]='JS每日一題'
Symbol用法
Symbol 目前有多種寫法
// 一
const title = Symbol()
const obj = {}
obj[title]='JS每日一題'
// 二
const obj = {
[title]:'JS每日一題'
}
// 三
Object.defineProperty(obj,title,{value:'JS每日一題'})
obj[title]
// 輸出的結果都爲JS每日一題
這裏注意一下,
Symbol
作爲屬性名時,不能用點去讀取
obj.title
// undefined
Symbol做爲屬性名,只有經過Object.getOwnPropertySymbols 方法返回
const attrs = Object.getOwnPropertySymbols(obj)
// [Symbol[title]]
Symbol.for()
若是咱們想要重複Symbol可使用Symbol.for, Smybol.for()及Smybol()的區別在於Symbol.for()會先去查找全局下有沒有聲明過,若是有就返回該值,沒有就新建一個,Symbol()每一次調用都會新建一個
代碼理解:
const title = Symbol.for('JS每日一題')
....
Symbol.for('JS每日一題')
//調用屢次都是使用的第一次聲明的值
Symbol.for('JS每日一題')
===
Symbol.for('JS每日一題')
// true
const title =Symbol('JS每日一題')
Symbol('JS每日一題')
===
Symbol('JS每日一題')
// false
總結
Symbol的特色
獨一無二
不能隱式轉換
不能與其它數據類型作運算
不能使用點運算符進行操做
九、簡述一下你爲何要使用vue?