1. 程式人生 > >web前端常見二十道面試題

web前端常見二十道面試題

01 作用域

var num1 = 55;
var num2 = 66;

function f1(num, num1){
    // var num = 55;
    // var num1 = 66;
    num = 100;
    num1 = 100;
    num2 = 100;
    console.log(num) // 100
    console.log(num1) // 100
    console.log(num2) // 100
}

f1(num1, num2)
console.log(num1) // 100
console.log(num2) // 66
console.log(num)
// 報錯 Uncaught ReferenceError: num is not defined

02 值型別和引用型別的傳遞

function Person(name,age,salary){
    this.name = name;
    this.age = age;
    this.salary = salary;
}

function f1(person){
    // var person = p
    person.name = "ls"
    person = new Person("aa", 23, 10)
}

var p = new Person("zs"
, 18, 1000) console.log(p.name) // zs f1(p) console.log(p.name) // ls

03 封裝函式進行字串駝峰命名的轉換

已知有字串foo = "get-lement-by-id",寫一個function將其轉化成駝峰命名錶示法"getElementById"

// 已知有字串foo = "get-lement-by-id",寫一個function將其轉化成駝峰命名錶示法"getElementById"
// var foo = "get-element-by-id";
function toUppercaseMessage(foo){
    // 根據某個字串進行切割
var arr = foo.split('-'); // 獲取元素中的第一個字元並轉換成大寫 for(var i = 0 ; i < arr.length ; i++){ // arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].substr(1, arr[i].length-1) // arr[i] = arr[i][0].toUpperCase() + arr[i].substring(1, arr[i].length) //arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].substr(1) arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].substring(1) } // 根據某個字元將陣列轉換成字串 return arr.join('') } console.log(toUppercaseMessage("get-element-by-id"));

04 氣泡排序

var arr = [5,43,32,20,122];
// 輪數
for(var i = 0 ; i < arr.length ; i++){
    // 次數
    for(var j = 0 ; j < arr.length - 1 - i ; j++){
        // 判斷前一個大於後一個數時進行交換
        if(arr[j] > arr[j+1]){
            // 藉助第三方變數交換兩個變數的值
            var temp = arr[j]
            arr[j] = arr[j+1]
            arr[j+1] = temp
        }
    }
}
console.log(arr)

05 翻轉陣列

var arr =[0,1,2,3,4,5,6,7,8,9];
for(var i = 0 ; i < arr.length / 2 ; i++){
    // arr[0]	arr[arr.length-1-0]
    // arr[1] 	arr[arr.length-1-1]
    // arr[2]	arr[arr.length-1-2]
    // arr[3] 	arr[arr.length-1-3]

    // 藉助第三方變數交換兩個變數的值 
    var temp =  arr[i];
    arr[i] = arr[arr.length - 1 - i];
    arr[arr.length - 1 - i] = temp;
}
console.log(arr)

06 去掉陣列中重複的資料

/**
 * 1. 建立一個新陣列,把原陣列中的第一個元素插入到新陣列中
 * 2. 遍歷原陣列中的每一個元素分別和新陣列中的每一個元素進行比較
 */
// 原陣列
var arr =[0,1,2,3,3,5,6,9,8,9];
// 新陣列
var temp = [];
temp[0] = arr[0]
// arr中的每個元素
for(var i = 0 ; i < arr.length ; i++){
    // t中的每個元素
    for(var j = 0 ; j < temp.length ; j++){
        // 當原陣列中的值和新陣列中的值相同的時候,就沒必要在進行比較了,跳出內迴圈。
        if(temp[j] == arr[i]){
            break;
        }
        // 拿原陣列中的某個元素比較到新陣列中的最後一個元素還沒有重複
        if(j == temp.length-1){
            // 將資料插入新陣列
            temp.push(arr[i]);
        }
    }
}
console.log(temp)

07 1物理畫素的實現

物理畫素 和 css畫素的關係:畫素比 = 物理畫素 / css畫素

  • 方法一
<style>
* {
    margin: 0;
    padding: 0;
}
#box {
    width: 0.5rem;
    height: 0.5rem;
    border-bottom: 1px solid #000;
}
</style>
<meta name="viewport" content="width=1, user-scalable=no, initial-scale=1.0">
<div id="box"></div>
window.onload = function(){
    // 畫素比
    var dpr = window.devicePixelRatio;
    // 縮放比例
    var scale = 1 / dpr;

    var width = document.documentElement.clientWidth;

    // 獲取meta標籤
    var metaNode = document.querySelector('meta[name="viewport"]');
    metaNode.setAttribute('content','width=1, user-scalable=no, initial-scale='+ scale)

    // 頁面中元素寬度、高度、比例反向乘回來
    var htmlNode = document.querySelector('html');
    htmlNode.style.fontSize = width * dpr + 'px';
}
  • 方法二
* {
    margin: 0;
    padding: 0;
}
#box {
    width: 200px;
    height: 200px;
    padding: relative;
}
#box::before {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 1px;
    background: #000;
}
@media screen and (-webkit-min-device-pixel-ratio: 2){
    #box::before {
        transform: scaleY(0.5)
    }
}
@media screen and (-webkit-min-device-pixel-ratio: 3){
    #box::before {
        transform: scaleY(0.333333)
    }
}
<meta name="viewport" content="width=1, user-scalable=no, initial-scale=1.0">
<div id="box"></div>
* {
    margin: 0;
    padding: 0;
}
#box {
    width: 200px;
    height: 200px;
    padding: relative;
}
#box::before {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 1px;
    background: #000;
}
@media screen and (-webkit-min-device-pixel-ratio: 2){
    #box::before {
        transform: scaleY(0.5)
    }
}
@media screen and (-webkit-min-device-pixel-ratio: 3){
    #box::before {
        transform: scaleY(0.333333)
    }
}

08 元素的水平垂直居中

* {
    margin: 0;
    padding: 0;
}
#wrap {
    width: 500px;
    height: 500px;
    background: grey;
    position: relative;
}
<div id="wrap">
    <div class="box"></div>
</div>
  • 方法一

#wrap .box {
    width: 200px;
    height: 200px;
    background: pink;
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}
  • 方法二
#wrap .box {
    width: 200px;
    height: 200px;
    background: pink;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%,-50%);
}
  • 方法三
#wrap .box {
    width: 200px;
    height: 200px;
    background: pink;
    position: absolute;
    left: 50%;
    top: 50%;
    margin-left: -100px;
    margin-top: -100px;
}
  • 方法四
#wrap {
    width: 500px;
    height: 500px;
    background: grey;
    display: flex;
    justify-content: center;
    align-items: center;
}
#wrap .box {
    width: 200px;
    height: 200px;
    background: pink;
}

09 用純css建立一個三角形

#box {
    width: 0px;
    height: 0px;
    border: 100px solid;
    border-top-color: red;
    border-right-color: transparent;
    border-bottom-color: transparent;
    border-left-color: transparent;
}
<div id="box"></div>

10 rem的適配

適配解決的問題是同一個元素在不同螢幕上呈現同樣的效果。

html根元素的字型大小設定為螢幕區域的寬

* {
     margin: 0;
     padding: 0;
}
#box {
    width: 0.5rem;
    height: 0.5rem;
    background: red;
}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div id="box"></div>
 window.onload = function(){
     // 獲取螢幕區域的寬度
     var width = document.documentElement.clientWidth;
     // 獲取html
     var htmlNode = document.querySelector('html');
     // 設定字型大小
     htmlNode.style.fontSize = width + 'px';
}

11 求背景圖片左邊到#box盒子左邊框外側的距離

* {
    margin: 0;
    padding: 0;
}
#box {
    width: 400px;
    height: 200px;
    background: pink;
    padding: 100px;					# 100px
    border: 100px solid blue;		 # 100px
    background-image: url("bg.jpg");  # 預設是從content開始的,即背景圖覆蓋padding
    background-repeat: no-repeat;
    background-origin: content-box;	  # 設定讓從padding開始
    background-position: -50px 0;	  # 向左便宜50
}
# 計算最終的值為 100 + 100 - 50 = 150px
<div id="box"></div>

12 js綜合面試題

/* function Foo(){
            getName = function(){
                alert(1);
                return this;
            }
        }
        Foo.getName = function(){
            alert(2)
        }
        Foo.prototype.getName = function(){
            alert(3)
        }
        var getName = function(){
            alert(4)
        }
        function getName(){
            alert(5)
        }*/


        // 變數提升後
        function Foo(){
            getName = function(){
                alert(1);
                return this;
            }
        }
        // var getName;
        function getName(){
            alert(5)
        }
        /***************************************/
        Foo.getName = function(){
            alert(2)
        }
        Foo.prototype.getName = function(){
            alert(3)
        }
        getName = function(){
            alert(4)
        }

        // 請寫出下列的輸出結果     .運算子優先順序最高
        Foo.getName(); // 2
        getName();  // 4
        // Foo().getName(); // (Foo()).getName() => window.getName()  1
        getName();  // 1
        new Foo.getName();  // new (Foo.getName)() ——> new (function(){alert(2)})()  2
        new Foo().getName(); // (new Foo()).getName() ——> foo.getName()  3
        new new Foo().getName();  // new ((new Foo()).getName)() ——> ——> new (function(){alert(3)})() 3

13 什麼是函式節流和函式防抖

  • 函式節流:一個函式執行一次後,只有大於設定的執行週期才會執行第二次

    • 有個需要頻繁觸發函式,處於優化效能角度,在規定時間內,只讓函式觸發的第一次生效,後面不生效

    • # 節流函式
      @param fn 要被節流的函式
      @param delay 規定的時間
      function throttle(fn, delay){
          // 記錄上一次函式觸發的時間
          var lastTime = 0;
          return function (){
              // 記錄當前函式觸發的時間
              var nowTime = Date.now() ;
      
              if(nowTime - lastTime > delay){
                  // 修改this的指向問題
                  fn.call(this);
                  fn()
                  // 同步時間
                  lastTime = nowTime;
              }
          }
      }
      document.onscroll = throttle(function(){
          console.log("scroll事件被觸發了"+Date.now())
      }, 200)
      
  • 防抖函式:一個需要頻繁觸發的函式,在規定的時間內,只讓最後一次生效,前面的不生效

    • function debounce(fn, delay){
          // 記錄上一次的延時器
          var timer = null;
          return function(){
              // 清除上一次延時器
              clearTimeouit(timer);
              // 重新設定新的延時器
              timer = setTimeout(function(){
                  fn().apply(this);
              }, delay);
          }
      }
      
      document.getElementById('btn').onclick = debounce(function(){
          console.log("防抖函式被觸發了" + Date.now())
      },1000)
      

14 什麼是跨域 ?解決跨域的辦法有哪些?

  1. 同源策略
    • 是瀏覽器安全策略
    • 協議、域名、埠號必須完全一致
  2. 跨域
    • 違背同源策略就會產生跨域
  3. 解決跨域
    • jsonp cors 伺服器代理
// 建立script標籤
var script = document.createElement('script')
// 設定回撥函式
function getData(data){
    // 資料請求回來會被觸發的函式
}
// 設定script的src屬性,設定請求地址
script.src = 'http://localhost:3000?callback=getData';
// 讓script生效
document.body.appendChild(script)

15 從一個url地址到最終頁面渲染完成,發生了什麼?

  1. DNS解析: 將域名地址解析為ip地址
    • 瀏覽器DNS快取
    • 系統DNS快取
    • 路由器DNS快取
    • 網路運營商DNS快取
    • 遞迴搜尋:blog.baidu.com
      • .com域名下查詢DNS解析
      • .baidu
      • blog
      • 出錯
  2. TCP連線: TCP三次握手
    • 第一次握手,由瀏覽器發起,告訴伺服器我要傳送請求了
    • 第二次握手,由伺服器發起,告訴瀏覽器我準備接收了,你趕緊傳送吧
    • 第三次握手,由瀏覽器傳送,告訴伺服器,我馬上就發了準備接受吧
  3. 傳送請求
    • 請求報文:HTTP協議的通訊內容
  4. 接受響應
    • 響應報文
  5. 渲染頁面
    • 遇見HTML標記,瀏覽器呼叫HTML解析器解析成Token並構建成dom樹
    • 遇見style/link標記,瀏覽器呼叫css解析器,處理css標記構建cssom樹
    • 遇到script標記,呼叫javascript解析器,處理script程式碼(繫結事件、修改dom樹、cssom樹)
    • 將dom樹和cssom樹 合併成一個渲染樹
    • 根據渲染