1. 程式人生 > 實用技巧 >面試題目1

面試題目1

面試題

https://juejin.im/post/5c8e409ee51d4534977bc557#heading-1

https://juejin.im/post/5d136700f265da1b7c6128db

https://juejin.im/post/5a6547d0f265da3e283a1df7

https://juejin.im/post/5e55272e6fb9a07ca453436f

https://www.jianshu.com/p/54cc04190252

https://juejin.im/post/5eace2176fb9a04340658974#heading-64

一、頁面佈局

(一)三欄佈局

float 佈局

  • 簡單且相容性好,需要清除浮動
<div class="box">
  <div class="left" style="float: left;">200px</div>
  <div class="right">200px</div>
  <div class="center" style="float: right;">自適應</div>
</div>

絕對佈局

  • 簡單且相容性好,但脫離文件流
<div class="box" style="position: relative;">
  <div class="left" style="position: absolute;left: 0;">200px</div>
  <div class="right" style="position: absolute;right: 0;">200px</div>
  <div class="center" style="margin: 0 200px;">自適應</div>
</div>

flex 佈局

  • 簡單,不支援 IE8 及以下
<div class="box" style="display: flex;">
  <div class="left" style="width:200px">200px</div>
  <div class="center" style="flex:1">自適應</div>
  <div class="right" style="width:200px">200px</div>
</div>

grid佈局

  • 簡單,不支援 IE8 及以下
<style>
    .box {
        width: 100%;
        display: grid;
        grid-template-columns: 200px auto 200px;
        grid-template-rows: 400px;
    }
</style>
<div class="box">
  <div class="left">200px</div>
  <div class="right">200px</div>
  <div class="center">自適應</div>
</div>

(二)水平垂直居中

絕對定位 position: absolute + transform

.container {
    position: relative;
}
.box {
    position:absolute;
    top:50%;
    left:50%;
    transform:translate(-50%, -50%);
    /*已知高度寬度,margin-top margin-left設定為本身高度寬度的1/2負值*/
}

絕對定位 position: absolute + margin: auto

  .container {
    width: 500px;
    height: 500px;
    border: 1px solid #000;
      
    position: relative;
  }
  .box {
    width: 200px;
    height: 200px;
    border: 1px solid #000;
    /*需知道子元素的寬高*/
    position: absolute;
    margin: auto;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  }

table

組合使用display:table-cell和vertical-align、text-align,使父元素內的所有行內元素水平垂直居中

/*利用 table 的單元格居中效果展示*/
.container {
    width: 300px;
    height: 300px;
    border: 1px solid #000;
    
    display: table-cell;
    text-align: center;
    vertical-align: middle;
}
.box {
    width: 100px;
    height: 100px;
    
    display: inline-block;
}

flex

.container {
    display:flex;
    justify-content: center;
    align-items:center;
}

grid

/*方法一:父元素指定子元素的對齊方式*/
.container {
    width: 500px;
    height: 500px;
    
    display:grid;
    justify-content: center;
	/*整個內容區域在容器裡面的水平位置*/    
    align-content: center;
    /*整個內容區域的垂直位置*/
  }


/*方法二:子元素自己指定自己的對齊方式*/
 .out{
    width: 300px;
    height: 300px;
     
    display: grid; 
  }

  .inner{
    width: 100px;
    height: 100px;
      
     justify-self: center;
    /*設定單元格內容的水平位置*/
    align-self:center;
    /*設定單元格內容的垂直位置*/
  }

二、CSS盒模型

(一)基礎概念

盒子模型組成:分為內容(content)、填充(padding)、邊框(border)和邊界(margin)

  • IE盒模型:屬性width,height包含content、border和padding

  • W3C標準盒模型:屬性width,height只包含內容content,不包含border和padding

(二)設定盒模型

/*設定IE模型*/
box-sizing: border-box;
/*設定標準模型*/
box-sizing: content-box;

(三)塊級格式化上下文 Block Formatting Context

頁面的基本單位是Box, 而元素的型別和 display 屬性,決定了 Box 的型別

不同型別的 Box 會參與不同的 Formatting Context ,Box內的元素會以不同的方式渲染

Formatting Context —— CSS2.1 規範中的一個概念。它是頁面中的一塊渲染區域,並且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關係和相互作用

盒子型別

  • block-level box

    • display 屬性為 block, list-item, table 等的元素
    • 生成 block-level box且參與 block fomatting context
  • inline-level box

    • display 屬性為 inline, inline-block, inline-table 等的元素
    • 生成 inline-level box且參與 inline formatting context
  • run-in box

BFC的佈局規則

  • 內部的盒子從頂端開始垂直地一個接一個地排列
  • 盒子之間垂直的間距是由 margin 決定的
  • 在同一個 BFC 中,兩個相鄰的塊級盒子的垂直外邊距會發生重疊
  • BFC 區域不會和 float box 發生重疊
  • BFC 能夠識別幷包含浮動元素,當計算其區域的高度時,浮動元素也參與計算
  • BFC在頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面的元素。反之也如此

建立BFC

(1)根元素
(2)浮動元素float=left|right或inherit(≠none)
(3)絕對定位元素position=absolute或fixed
(4)overflow=hidden|auto或scroll(≠visible)
(5)display=inline-block|flex|inline-flex|table-cell或table-caption

BFC 的作用

  1. 包含浮動元素(清除浮動)

    • 浮動元素會脫離文件流(絕對定位元素也會脫離文件流),導致無法計算準確的高度,這種問題稱為高度塌陷

    • 解決高度塌陷問題的前提是能夠識別幷包含浮動元素,也就是清除浮動

    解決方法:在容器(container)中建立 BFC

  2. 避免外邊距摺疊

    外邊距摺疊(Margin collapsing)只會發生在屬於同一BFC的塊級元素之間。如果它們屬於不同的 BFC,它們之間的外邊距則不會摺疊

三、DOM事件

(一)事件流

  • 事件冒泡(Event Bubbling)——從下往上的傳播方式,當一個元素(文件中巢狀層次最深的節點)接收到事件的時會將該事件傳給自己的父級直到頂部
  • 事件捕獲(Event Capturing)——與事件冒泡相反

(二)事件模型

DOM0級模型

  • 繫結監聽函式

    • HTML程式碼中直接繫結:<button onclick="handleClick()">Press me</button>
    • JS程式碼指定屬性值:element.onclick = function(){}
  • 刪除事件處理

    • element.onclick = null
  • 事件不會傳播,即沒有事件流的概念

DOM2級模型

  • 繫結監聽函式

    • element.addEventListener('click', function(){}, false)
  • 刪除事件處理

    • element.removeEventListener('mousedown', handleMouseDown, false)
  • 可以新增多個相同事件的處理程式

  • 事件傳播:2級DOM的事件傳播分三個階段進行

(三)事件物件

當一個事件被觸發時,會建立一個事件物件(Event Object), 這個物件裡面包含了與該事件相關的屬性或者方法。該物件會作為第一個引數傳遞給監聽函式

  • DOM事件模型中的事件物件常用屬性:
    • type用於獲取事件型別
    • target獲取事件目標
    • stopPropagation()阻止事件冒泡
    • preventDefault()阻止事件預設行為
  • IE事件模型中的事件物件常用屬性:
    • type用於獲取事件型別
    • srcElement獲取事件目標
    • cancelBubble阻止事件冒泡
    • returnValue阻止事件預設行為

(四)事件代理 / 委託

事件代理本質

  • 利用事件冒泡的機制,父級元素可以通過事件物件獲取到觸發事件的目標元素,可以把子節點的監聽函式定義在父節點上,由父節點的監聽函式統一處理多個子元素的事件

事件代理優勢

  • 減少事件註冊,節省記憶體佔用
  • 新增子物件時無需再次對其繫結事件,適合動態新增元素

事件代理例項

<ul id="parent">
  <li class="child">one</li>
  <li class="child">two</li>
  <li class="child">three</li>
</ul>

<script type="text/javascript">
  //父元素
  var dom= document.getElementById('parent');

  //父元素繫結事件,代理子元素的點選事件
  dom.onclick= function(event) {
    var event= event || window.event;
    var curTarget= event.target || event.srcElement;

    if (curTarget.tagName.toLowerCase() == 'li') {
      //事件處理
    }
  }
</script>

(五)事件廣播

var event= new Event('build'); 

// listener for the event
element.addEvenetListener('build', function(e) {...}, false);

//Dispatch the event 
element.dispatchEvent(event);

四、HTTP協議

五、原型鏈

(一)原型、建構函式、例項、原型鏈

  • 每個函式都有一個prototype屬性指向原型物件。原型物件包含所有例項共享的屬性和方法
  • 每個原型都有一個constructor指標,用來指向Prototype屬性所在的函式
  • 瀏覽器為例項物件提供一個__proto__屬性,用來指向建構函式的原型物件
    • 獲取例項的原型建議使用 Object.getPrototypeOf(obj) 返回指定物件的原型(內部[[Prototype]]屬性的值)
  • 當原型物件等於其他型別的例項,形成遞進關係直到Object.prototype,叫做原型鏈

(二)instanceof 的原理

instanceof 用於檢測建構函式的 prototype 屬性是否出現在某個例項物件的原型鏈上

(三) 判斷變數的型別

  • typeof
    • 基礎資料型別:除了 null返回 "object",其他的正確返回
    • 引用型別:除了函式會返回 "function",其他的返回 "object"
  • instanceof
    • Date instanceof Object
  • Object.prototype.toString.call(..)——tpyeof返回 object的物件,內部具有[[class]]屬性用於進一步區分型別
    • Object.prototype.toString.call( [1,2,3] ); //"[object Array]"
  • variableName === void 0—— 判斷是否等於 undefined

(四) new操作符

new呼叫建構函式的步驟

  1. 建立空物件
  2. 將this指向建立的空物件——建構函式作用域賦給空物件
  3. 執行建構函式的程式碼——為新物件新增屬性
  4. 返回新物件

手動實現new

function Person(name, age){
    this.name = name;
    this.age = age;
}
function _new() {
 	//1.獲取建構函式  
    let Func = [].shift.call(arguments)
    
    //2.建立一個空物件obj,並讓其繼承Func.prototype
    let obj = Object.create(Func.prototype)
    // var obj = {}
	// obj.__proto__ = Func.prototype
    
    //3.執行建構函式,並將this指向建立的空物件obj
    let res = Func.apply(obj, arguments)
    
    //4.如果建構函式返回的值是物件則返回,不是物件則返回建立的物件obj
    return typeof res === 'object' ? res : obj
}
var p1 = _new(Person, '小魚', 18)

Object.create()方法建立一個新物件,使用現有的物件來提供新建立的物件的__proto__

六、面向物件

(一)面向物件 OOP

  • 封裝:低耦合高內聚
  • 多型:過載和重寫
    • 過載:方法名相同,形參的個數或型別相同
    • 重寫:在類的繼承中,子類可以重寫父類中的方法
  • 繼承:子類繼承父類的方法

(二)建立物件的方法

工廠模式

  • 描述:用函式封裝以特定介面建立物件的細節
function createPerson(name, age, job) {
    let o = new Object()
    o.name = name
    o.age = age
    o.job = job
    o.sayName() {
      console.log(this.name);
    }
    return o
}
var p1 = createPerson('小魚',18,'web');
p1.sayName();   //小魚
var p2 = createPerson('xiaoyu',22,'java');
p2.sayName();   //xiaoyu
  • 缺點:不能識別物件型別

建構函式模式

  • 描述:建立自定義的建構函式,從而定義特定型別物件的屬性和方法
function Person(name, age, job) {
    this.name = name
    this.age = age
    this.job = job
    this.sayName  = function() {
       console.log(this.name); 
    }
}
var p1 = new Person('小魚', 18, 'Web');
var p2 = new Person('xiaoyu', 22, 'java');

//建立物件具有特定型別
p1.constructor === Person //true 
//不同的例項上的同名函式是不相等的
p1.sayName === p2.sayName;  
  • 缺點:每個例項的屬性和方法重新建立,浪費記憶體空間

如果將建構函式中的函式定義為全域性的函式,可以解決同名函式不共享的問題。但是破壞了自定義型別的封裝性

原型模式

  • 描述:建立的每個函式都有原型屬性prototype,指向特定型別所有共享的屬性和方法
function Person() {}
Person.prototype = {
    name:'小魚',
    age:18,
    job:'Web',
    sayName:function(){
        console.log(this.name);
    }
};
var p1 = new Person();
console.log(p1.constructor);	//[Function: Object]
  • 缺點:對於引用型別的屬性,一個例項對其進行修改,也會反映在其他例項上

組合使用建構函式和原型模式

  • 描述:建構函式模式定義例項屬性,原型模式定義方法和共享的屬性
function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ['Shelby','Court'];
}
Person.prototype = {
    constructor:Person,
    sayName:function(){
        console.log(this.name);
    }
};
var p1 = new Person('小魚',18,'Web');
var p2 = new Person('xioayu',22,'Java');
p1.friends.push('biu');
console.log(p1.friends);   //[ 'Shelby', 'Court', 'biu' ]
console.log(p2.friends);   //[ 'Shelby', 'Court' ]

動態原型模式

  • 描述:把所有資訊都封裝在建構函式中,通過判斷某一方法是否存在來決定是否需要初始化原型
function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ['Shelby','Court'];
    if(typeof this.sayName !== 'function'){
        Person.prototype.sayName = function(){   
            console.log(this.name);
        }
    }
}
var p1 = new Person('小魚', 18,'Web');
p1.sayName();   //小魚

(三)類的繼承

建構函式繼承

借用建構函式:在子類建構函式內部呼叫超類建構函式