前端知識點(二)

一、元素上下垂直居中的方式有哪些?

元素水平垂直居中的方式有哪些?

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?

相關文章
相關標籤/搜索