前端面試題

自己收集的一些前端面試題,部分來(lái)自網(wǎng)絡(luò),部分自己寫(xiě)的,不保證正確,如有錯(cuò)誤可以評(píng)論告知。

前端性能優(yōu)化有哪些?
1.減少HTTP請(qǐng)求數(shù)
2.合理設(shè)置 HTTP緩存,很少變化的資源可以直接通過(guò) HTTP Header中的Expires設(shè)置
一個(gè)很長(zhǎng)的過(guò)期頭 ;變化不頻繁而又可能會(huì)變的資源可以使用 Last-Modifed來(lái)做請(qǐng)求驗(yàn)證
3.html,css,js,圖片等資源的合并/壓縮
4.CSS Sprites(精靈圖)
5.Inline Images(base64圖片)
6.懶加載
7.代碼按需加載(webpack)
8.'將js放于頁(yè)面的底部,css放于頂部',讓瀏覽器先加載css與html結(jié)構(gòu),以便更早的渲染出
頁(yè)面結(jié)構(gòu),腳本的運(yùn)行會(huì)阻礙資源的加載.
9.'為script增加async 或 defer來(lái)異步加載腳本'
10.避免過(guò)多的操作DOM節(jié)點(diǎn)
11.使用CDN(根據(jù)用戶ip,獲取就進(jìn)服務(wù)上的靜態(tài)資源,加快訪問(wèn)速度)
12.添加 link dns-prefetch 對(duì)于訪問(wèn)過(guò)的地址直接跳過(guò)dns解析
輸入url按下回車(chē)后發(fā)生了什么?
1.解析URL
2.DNS解析,將域名解析為IP(本地,DNS服務(wù)器,如果查找不到,頁(yè)面則無(wú)法訪問(wèn))
3.通過(guò)TCP協(xié)議,向服務(wù)器發(fā)送請(qǐng)求(三次握手,建立連接)
4.瀏覽器向web服務(wù)器發(fā)起HTTP請(qǐng)求
5.服務(wù)器接收請(qǐng)求,響應(yīng)請(qǐng)求
6.瀏覽器接收響應(yīng),開(kāi)始下載并渲染,將頁(yè)面呈現(xiàn)在我們面前
  {
    解析HTML生成DOM樹(shù),
    解析CSS文件生成CSSOM樹(shù),
    并解析Javascript代碼
    CSS和DOM組合形成渲染樹(shù),
    進(jìn)行布局,在瀏覽器中繪制渲染樹(shù)中節(jié)點(diǎn)的屬性(位置,寬度,大小等)
    繪制元素,繪制各個(gè)節(jié)點(diǎn)的可視屬性(顏色背景等,此時(shí)可能會(huì)形成多個(gè)圖層)
    合并圖層,將頁(yè)面呈現(xiàn)給用戶面前
  }
強(qiáng)緩存和協(xié)商緩存

強(qiáng)緩存

強(qiáng)緩存是利用http的返回頭中的Expires或Cache-Control兩個(gè)字段來(lái)控制的,用來(lái)表示資源的緩存時(shí)間。

Expires是http1.0的規(guī)范,值為一個(gè)絕對(duì)時(shí)間的GMT格式的時(shí)間字符串,這個(gè)時(shí)間代
表著資源的失效時(shí)間,在此時(shí)間之前,即命中緩存。這種方式有一個(gè)明顯的缺點(diǎn),由
于失效時(shí)間是一個(gè)絕對(duì)時(shí)間,所以當(dāng)服務(wù)器與客戶端時(shí)間偏差較大時(shí),就會(huì)導(dǎo)致緩存混亂。

Cache-Control是http1.1時(shí)出現(xiàn)的,主要是利用該字段的`max-age`值來(lái)進(jìn)行判斷,它
是一個(gè)相對(duì)時(shí)間,例如Cache-Control:max-age=3600,代表著資源的有效期是3600
秒。
注: Expires與Cache-Control同時(shí)啟用的時(shí)候Cache-Control優(yōu)先級(jí)高。

協(xié)商緩存

協(xié)商緩存是由服務(wù)器來(lái)確定緩存資源是否可用,所以客戶端與服務(wù)器端要通過(guò)某種標(biāo)識(shí)來(lái)進(jìn)行通信,從而讓
服務(wù)器判斷請(qǐng)求資源是否可以緩存訪問(wèn),這主要涉及到下面兩組header字段,這兩組搭檔都是成對(duì)出現(xiàn)的,
即第一次請(qǐng)求的響應(yīng)頭帶上某個(gè)字段(Last-Modified或者Etag),則后續(xù)請(qǐng)求則會(huì)帶上對(duì)應(yīng)的請(qǐng)求字段(If-
Modified-Since或者If-None-Match),若響應(yīng)頭沒(méi)有Last-Modified或者Etag字段,則請(qǐng)求頭也不會(huì)有對(duì)應(yīng)的
字段。

Last-Modify/If-Modify-Since

第一次請(qǐng)求資源,服務(wù)器會(huì)加上Last-Modify,一個(gè)時(shí)間標(biāo)識(shí)該資源的最后修改時(shí)間,
再次請(qǐng)求時(shí),request的請(qǐng)求頭中會(huì)包含If-Modify-Since,該值為緩存之前返回的Last-
Modify。服務(wù)器收到If-Modify-Since后,根據(jù)資源的最后修改時(shí)間判斷是否命中緩存。
如果命中緩存,則返回304,并且不會(huì)返回資源內(nèi)容,并且不會(huì)返回Last-Modify。

ETag/If-None-Match

Etag/If-None-Match返回的是一個(gè)校驗(yàn)碼。ETag可以保證每一個(gè)資源是唯一的,資源
變化都會(huì)導(dǎo)致ETag變化。服務(wù)器根據(jù)瀏覽器上送的If-None-Match值來(lái)判斷是否命中緩存。
注: ETag 優(yōu)先級(jí)高于 Last-Modified
iframe有那些缺點(diǎn)?
  *iframe會(huì)阻塞主頁(yè)面的Onload事件;
  *爬蟲(chóng)無(wú)法解讀這種頁(yè)面,不利于SEO;
  *iframe和主頁(yè)面共享連接池,而瀏覽器對(duì)相同域的連接有限制,所以會(huì)影響頁(yè)面的并行加載。

  使用iframe之前需要考慮這兩個(gè)缺點(diǎn)。如果需要使用iframe,最好是通過(guò)javascript
  動(dòng)態(tài)給iframe添加src屬性值,這樣可以繞開(kāi)以上兩個(gè)問(wèn)題。
CSS的盒子模型
IE 盒模型、標(biāo)準(zhǔn)盒模型
盒模型: 內(nèi)容(content)、填充(padding)、邊界(margin)、 邊框(border)
區(qū)  別: IE的content部分把 border 和 padding計(jì)算了進(jìn)去
BFC
塊級(jí)格式化上下文
具有 BFC 特性的元素可以看作是隔離了的獨(dú)立容器,'容器里面的元素不會(huì)在布局上影響到外面的元素',并且 BFC 具有普通容器所沒(méi)有的一些特性。

觸發(fā)BFC: 
浮動(dòng)元素:float 除 none 以外的值
絕對(duì)定位元素:position (absolute、fixed)
display 為 inline-block、table-cells、flex
overflow 除了 visible 以外的值 (hidden、auto、scroll)
new操作符具體干了什么
 1、創(chuàng)建一個(gè)空對(duì)象,并且 this 變量引用該對(duì)象,同時(shí)還繼承了該函數(shù)的原型。
 2、屬性和方法被加入到 this 引用的對(duì)象中。
 3、新創(chuàng)建的對(duì)象由 this 所引用,并且最后隱式的返回 this 。
 var obj  = {};
 obj.__proto__ = Base.prototype;
 Base.call(obj);
實(shí)現(xiàn)一個(gè) new 操作符
function New(func) {
    var res = {};
    if (func.prototype !== null) {
        res.__proto__ = func.prototype;
    }
    var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
    if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
        return ret;
    }
    return res;
}
var obj = New(A, 1, 2);
// equals to
var obj = new A(1, 2);
實(shí)現(xiàn)call、apply 與 bind
// call
Function.prototype.myCall = function(context) {
  if (typeof this !== 'function') {
    throw new TypeError('Error')
  }
  context = context || window
  context.fn = this
  const args = [...arguments].slice(1)
  const result = context.fn(...args)
  delete context.fn
  return result
}

// apply,apply與call的區(qū)別在于對(duì)參數(shù)的處理
Function.prototype.myApply = function(context) {
  if (typeof this !== 'function') {
    throw new TypeError('Error')
  }
  context = context || window
  context.fn = this
  let result
  // 處理參數(shù)和 call 有區(qū)別
  if (arguments[1]) {
    result = context.fn(...arguments[1])
  } else {
    result = context.fn()
  }
  delete context.fn
  return result
}

// bind
Function.prototype.myBind = function (context) {
  if (typeof this !== 'function') {
    throw new TypeError('Error')
  }
  const _this = this
  const args = [...arguments].slice(1)
  // 返回一個(gè)函數(shù)
  return function F() {
    // 因?yàn)榉祷亓艘粋€(gè)函數(shù),我們可以 new F(),所以需要判斷
    if (this instanceof F) {
      return new _this(...args, ...arguments)
    }
    return _this.apply(context, args.concat(...arguments))
  }
}
實(shí)現(xiàn) instanceOf
function instanceOf(left,right) {
    let proto = left.__proto__;
    let prototype = right.prototype
    while(true) {
        if(proto == null) return false
        if(proto == prototype) return true
        proto = proto.__proto__;
    }
}
PC端常見(jiàn)兼容問(wèn)題
1.IE6浮動(dòng)的雙被邊距bug
解決方法:為其增加display:inline;屬性
2.IE8的input沒(méi)有placeholder
解決方法:內(nèi)容為空且沒(méi)有focus,為其設(shè)置默認(rèn)文字,focus時(shí)去除默認(rèn)文字;未focus且已輸入文字,則不設(shè)置默認(rèn)文字
3.不同瀏覽器的標(biāo)簽?zāi)J(rèn)的margin和padding不同
解決方法:重置所有標(biāo)簽{margin:0;padding:0;}
4.li標(biāo)簽之間有空白
解決方法:1. 標(biāo)簽不要換行,首尾連接;2. 父元素設(shè)置 display:inline;3. 父元素設(shè)置 font-size: 0;
5.margin重疊(取最大的)
解決方法:兩個(gè)元素外包一層div,為該div怎加overflow:hidden;(BFC)
手機(jī)端兼容問(wèn)題
1.字體、圖片模糊
解決方法:由于像素比的原因,可根據(jù)設(shè)備像素比,動(dòng)態(tài)設(shè)置meta的縮放比例。
2.ios fixed bug
解決方法:(1) header main footer 全部fixed,main區(qū)域overflow: hidden; mian區(qū)域的輸入框focus,就沒(méi)有問(wèn)題。
(2)focus時(shí),fixed改為absolute
3.點(diǎn)擊iOS的可點(diǎn)擊的元素時(shí),覆蓋顯示的高亮顏色。
解決方法:-webkit-tap-highlight-color:transparent;
4.ios中滾動(dòng)區(qū)域卡頓
解決方法:webkit-overflow-scrolling: touch; overflow-scrolling: touch;
5.Retina屏的1px邊框
解決方法:設(shè)置1px的div,將其縮放0.5。
6.transition閃屏
解決方法:
/設(shè)置內(nèi)嵌的元素在3D 空間如何呈現(xiàn):保留3D /
-webkit-transform-style: preserve-3d;
/ 設(shè)置進(jìn)行轉(zhuǎn)換的元素的背面在面對(duì)用戶時(shí)是否可見(jiàn):隱藏 / 
-webkit-backface-visibility:hidden;
7.移動(dòng)端點(diǎn)擊300ms延遲
解決方法:產(chǎn)生的原因是手機(jī)要檢測(cè)雙擊,解決的方法可以用zepto的tap事件,或者使用fastclick.js,或者自己使用touch相關(guān)事件來(lái)取代click。
8.Retina屏的1px邊框
解決方法:設(shè)置1px的div,將其縮放0.5。
js繼承參考這里(https://www.cnblogs.com/humin/p/4556820.html
ajax
// GET
//步驟一:創(chuàng)建異步對(duì)象
var ajax = new XMLHttpRequest();
//步驟二:設(shè)置請(qǐng)求的url參數(shù),參數(shù)一是請(qǐng)求的類(lèi)型,參數(shù)二是請(qǐng)求的url,可以帶參數(shù),動(dòng)態(tài)的傳遞參數(shù)starName到服務(wù)端
ajax.open('get','getStar.php?starName='+name);
//步驟三:發(fā)送請(qǐng)求
ajax.send();
//步驟四:注冊(cè)事件 onreadystatechange 狀態(tài)改變就會(huì)調(diào)用
ajax.onreadystatechange = function () {
   if (ajax.readyState==4 &&ajax.status==200) {
    //步驟五 如果能夠進(jìn)到這個(gè)判斷 說(shuō)明 數(shù)據(jù) 完美的回來(lái)了,并且請(qǐng)求的頁(yè)面是存在的
    console.log(xml.responseText);//輸入相應(yīng)的內(nèi)容
    }
}
// POST
//創(chuàng)建異步對(duì)象  
var xhr = new XMLHttpRequest();
//設(shè)置請(qǐng)求的類(lèi)型及url
//post請(qǐng)求一定要添加請(qǐng)求頭才行不然會(huì)報(bào)錯(cuò)
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
 xhr.open('post', '02.post.php' );
//發(fā)送請(qǐng)求
xhr.send('name=fox&age=18');
xhr.onreadystatechange = function () {
    // 這步為判斷服務(wù)器是否正確響應(yīng)
  if (xhr.readyState == 4 && xhr.status == 200) {
    console.log(xhr.responseText);
  } 
};
jq大致原理
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<script>
    (function(window){
        function Jquery (el) {
            return new Jquery.fn.init(el)
        }
        Jquery.fn = Jquery.prototype = {
            constructor: Jquery,
            init: function (el) {
                var el = document.querySelectorAll(el)
                this.length = el.length
                for (var i = 0; i < el.length; i++) {
                    this[i] = el[i]
                }
            },
            each: function (cb) {
                for (var i = 0; i < this.length; i++) {
                    cb.call(this[i], this[i], i)
                }
            },
            get:  function (index) {
                return this[index]
            },
            html: function (param) {
                if(typeof param !== "undefined"){
                    this.each(function(){
                        this.innerHTML = param
                    })
                }else{
                    return this[0].innerHTML
                }
                return this
            }
        }
        Jquery.fn.init.prototype = Jquery.fn 
        // jq的方法定義在Jquery.prototype上,
        // Jquery.prototype.init的原型上并沒(méi)有方法
        // 這一句Jquery.prototype.init與Jquery共享原型

        window.$ = Jquery
    })(window)

    // 擴(kuò)展一個(gè)方法
    $.fn.get1 = function (index) {
        return this[index]
    }
</script>
<body>
    <h1 class="app">1</h1>
    <h1 class="app">2</h1>
    <h1 id="app"></h1>
</body>
<script>
    console.log($('.app').get(0))
    $('.app').each(function(e, i){
        console.log(e)
        console.log(i)
    })
    $('#app').html('FakeJquery')
</script>
</html>
vue原理
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Two-way data-binding</title>
</head>
<body>
  
  <div id="app">
    <input type="text" v-model="text">
    {{ text }}
  </div>

  <script>
    function observe (obj, vm) {
      Object.keys(obj).forEach(function (key) {
        defineReactive(vm, key, obj[key]);
      });
    }
    function defineReactive (obj, key, val) {
      var dep = new Dep();
      Object.defineProperty(obj, key, {
        get: function () {
          // 添加訂閱者watcher到主題對(duì)象Dep
          if (Dep.target) dep.addSub(Dep.target);
          return val
        },
        set: function (newVal) {
          if (newVal === val) return
          val = newVal;
          // 作為發(fā)布者發(fā)出通知
          dep.notify();
        }
      });
    }
    function nodeToFragment (node, vm) {
      var flag = document.createDocumentFragment();
      var child;
      
      while (child = node.firstChild) {
        compile(child, vm);
        flag.appendChild(child); // 將子節(jié)點(diǎn)劫持到文檔片段中
      }
      return flag;
    }
    function compile (node, vm) {
      var reg = /\{\{(.*)\}\}/;
      // 節(jié)點(diǎn)類(lèi)型為元素
      if (node.nodeType === 1) {
        var attr = node.attributes;
        // 解析屬性
        for (var i = 0; i < attr.length; i++) {
          if (attr[i].nodeName == 'v-model') {
            var name = attr[i].nodeValue; // 獲取v-model綁定的屬性名
            node.addEventListener('input', function (e) {
              // 給相應(yīng)的data屬性賦值,進(jìn)而觸發(fā)該屬性的set方法
              vm[name] = e.target.value;
            });
            node.value = vm[name]; // 將data的值賦給該node
            node.removeAttribute('v-model');
          }
        };
        new Watcher(vm, node, name, 'input');
      }
      // 節(jié)點(diǎn)類(lèi)型為text
      if (node.nodeType === 3) {
        if (reg.test(node.nodeValue)) {
          var name = RegExp.$1; // 獲取匹配到的字符串
          name = name.trim();
          new Watcher(vm, node, name, 'text');
        }
      }
    }
    function Watcher (vm, node, name, nodeType) {
      Dep.target = this;
      this.name = name;
      this.node = node;
      this.vm = vm;
      this.nodeType = nodeType;
      this.update();
      Dep.target = null;
    }
    Watcher.prototype = {
      update: function () {
        this.get();
        if (this.nodeType == 'text') {
          this.node.nodeValue = this.value;
        }
        if (this.nodeType == 'input') {
          this.node.value = this.value;
        }
      },
      // 獲取data中的屬性值
      get: function () {
        this.value = this.vm[this.name]; // 觸發(fā)相應(yīng)屬性的get
      }
    }
    function Dep () {
      this.subs = []
    }
    Dep.prototype = {
      addSub: function(sub) {
        this.subs.push(sub);
      },
      notify: function() {
        this.subs.forEach(function(sub) {
          sub.update();
        });
      }
    };
    function Vue (options) {
      this.data = options.data;
      var data = this.data;
      observe(data, this);
      var id = options.el;
      var dom = nodeToFragment(document.getElementById(id), this);
      // 編譯完成后,將dom返回到app中
      document.getElementById(id).appendChild(dom); 
    }
    var vm = new Vue({
      el: 'app',
      data: {
        text: 'hello world'
      }
    });
  </script>

</body>
</html>
算法
// 1.冒泡 O(n2)
// <1>.比較相鄰的元素。如果第一個(gè)比第二個(gè)大,就交換它們兩個(gè);
// <2>.對(duì)每一對(duì)相鄰元素作同樣的工作,從開(kāi)始第一對(duì)到結(jié)尾的最后一對(duì),這樣在最后的元素應(yīng)該會(huì)是最大的數(shù);
// <3>.針對(duì)所有的元素重復(fù)以上的步驟,除了最后一個(gè);
// <4>.重復(fù)步驟1~3,直到排序完成。
var arr1 = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48]
function bubbleSort (arr) {
    var len = arr.length
    for (var i = 0; i < len; i++) {
        for (var j = 0; j < len - 1 - i; j++) {
            if (arr[j] > arr[j+1]) {
                var t = arr[j+1]
                arr[j+1] = arr[j]
                arr[j] = t
            }
        }
        console.log(arr)
    }
    return arr
}
console.log(bubbleSort(arr1))

// 2.快排 O(nlogn)
// <1>.從數(shù)列中挑出一個(gè)元素,稱(chēng)為 “基準(zhǔn)”(pivot);
// <2>.重新排序數(shù)列,所有元素比基準(zhǔn)值小的擺放在基準(zhǔn)前面,所有元素比基準(zhǔn)值大的擺在基準(zhǔn)的后面(相同的數(shù)可以到任一邊)。在這個(gè)分區(qū)退出之后,該基準(zhǔn)就處于數(shù)列的中間位置。這個(gè)稱(chēng)為分區(qū)(partition)操作;
// <3>.遞歸地(recursive)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。
var arr2 = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48]
function quickSort (arr) {
    console.time('2.快速排序耗時(shí)')
    if (arr.length <= 1) return arr
    var num = arr.splice(0, 1)
    // console.log(num)
    var left = []
    var right = []
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] < num) {
            left.push(arr[i])
        } else {
            right.push(arr[i])
        }
    }
    // console.log(left)
    // console.log(right)
    console.timeEnd('2.快速排序耗時(shí)')
    return quickSort(left).concat(num, quickSort(right))
}
console.log(quickSort(arr2))

// 3.選擇排序 O(n2)
// <1>.初始狀態(tài):無(wú)序區(qū)為R[1..n],有序區(qū)為空;
// <2>.第i趟排序(i=1,2,3…n-1)開(kāi)始時(shí),當(dāng)前有序區(qū)和無(wú)序區(qū)分別為R[1..i-1]和R(i..n)。該趟排序從當(dāng)前無(wú)序區(qū)中-選出關(guān)鍵字最小的記錄 R[k],將它與無(wú)序區(qū)的第1個(gè)記錄R交換,使R[1..i]和R[i+1..n)分別變?yōu)橛涗泜€(gè)數(shù)增加1個(gè)的新有序區(qū)和記錄個(gè)數(shù)減少1個(gè)的新無(wú)序區(qū);
// <3>.n-1趟結(jié)束,數(shù)組有序化了。
// 每次循環(huán)選擇最小的數(shù),將其放到前面
var arr3 = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48]
function selectionSort (arr) {
    var minIndex // 當(dāng)前循環(huán)最小索引
    for (var i = 0; i < arr.length - 1; i++) { // arr.length - 1 最后一個(gè)就是最大的
        minIndex = i // 默認(rèn)當(dāng)前最小索引為外層循環(huán)的第一個(gè)
        for (var j = i + 1; j < arr.length; j++) { // 內(nèi)循環(huán)比外循環(huán)索引多1
            if( arr[j] < arr[minIndex] ){ // 內(nèi)循環(huán)的沒(méi)一個(gè)與當(dāng)前外循環(huán)對(duì)比
                // 保存當(dāng)前最小索引為 j
                minIndex = j
                // console.log(minIndex)
            }
        }
        // 交換當(dāng)前最小值
        var t = arr[i]
        arr[i] = arr[minIndex]
        arr[minIndex] = t
        // console.log(arr[i])
        // console.log(arr[minIndex])
    }
    return arr
}
console.log(selectionSort(arr3))


// 4.插入排序 O(n2)
// <1>.從第一個(gè)元素開(kāi)始,該元素可以認(rèn)為已經(jīng)被排序;
// <2>.取出下一個(gè)元素,在已經(jīng)排序的元素序列中從后向前掃描;
// <3>.如果該元素(已排序)大于新元素,將該元素移到下一位置;
// <4>.重復(fù)步驟3,直到找到已排序的元素小于或者等于新元素的位置;
// <5>.將新元素插入到該位置后;
// <6>.重復(fù)步驟2~5。
var arr4 = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48]
function insertionSort (arr) {
    if (arr.length <= 1) return arr
    for (var i = 0; i < arr.length; i++) {
        var key = arr[i]
        var j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
    return arr
}
console.log(insertionSort(arr4))




// 5.歸并排序 O(nlogn)
// <1>.把長(zhǎng)度為n的輸入序列分成兩個(gè)長(zhǎng)度為n/2的子序列;
// <2>.對(duì)這兩個(gè)子序列分別采用歸并排序;
// <3>.將兩個(gè)排序好的子序列合并成一個(gè)最終的排序序列。
var arr5 = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48]
function mergeSort (arr) {
    var len = arr.length
    if(len <= 1) return arr
    var middle = Math.floor(len / 2) // 中間值
    var left = arr.slice(0, middle) // 
    var right = arr.slice(middle)
    return merge(mergeSort(left), mergeSort(right))
}
function merge (left, right) {
    var result = [];
    while (left.length && right.length) {
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }
    while (left.length)
        result.push(left.shift());
    while (right.length)
        result.push(right.shift());
    return result;
}
console.log(mergeSort(arr))

/*  */
// 數(shù)組去重1
var arr6 = [3,2,3,5,47,15,3,26,4,2,46,4,19,5,48]
var removeReapt = new Set(arr6)
console.log([...removeReapt])

// 數(shù)組去重2
var arr7 = [3,2,3,5,47,15,3,26,4,2,46,4,19,5,48]
function rReapt (arr) {
    var array = []
    for (var i = 0; i < arr.length; i++) {
        if (array.indexOf(arr[i]) == -1) {
            array.push(arr[i])
        }
        
    }
    return array
}
console.log(rReapt(arr7))


// 數(shù)組去重3
var arr8 = [3,2,3,5,47,15,3,26,4,2,46,4,19,5,48]
function rReapt2 (arr) {
    var obj = {}
    var array = []
    for (var i = 0; i < arr.length; i++) {
        if (!arr[i] in obj) {
            obj[arr[i]] = true
        }
    }
    for (var x in obj){
        array.push(x)
    }
    return array
}
console.log(rReapt(arr7))


參考:
移動(dòng)端兼容:https://blog.csdn.net/hardgirls/article/details/51722519
js繼承:https://www.cnblogs.com/humin/p/4556820.html
vue原理:http://www.itdecent.cn/p/c2fa36835d77
算法:https://www.cnblogs.com/beli/p/6297741.html
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.一些開(kāi)放性題目 1.自我介紹:除了基本個(gè)人信息以外,面試官更想聽(tīng)的是你與眾不同的地方和你的優(yōu)勢(shì)。 2.項(xiàng)目介紹...
    55lover閱讀 701評(píng)論 0 6
  • 在線閱讀 http://interview.poetries.top[http://interview.poetr...
    前端進(jìn)階之旅閱讀 115,534評(píng)論 24 450
  • 面試題一:https://github.com/jimuyouyou/node-interview-questio...
    R_X閱讀 1,758評(píng)論 0 5
  • 【轉(zhuǎn)載】CSDN - 張林blog http://blog.csdn.net/XIAOZHUXMEN/articl...
    竿牘閱讀 3,587評(píng)論 1 14
  • D17~3月11日 今天讀《圣經(jīng)》創(chuàng)世記,讀到50 :19 約瑟對(duì)他們說(shuō):“不要害怕,我豈能代替 神呢?”這...
    林林Amy閱讀 340評(píng)論 0 0

友情鏈接更多精彩內(nèi)容