javascript常見知識點彙總

從輸入網址到渲染完成經歷了哪些過程?

  1. 輸入網址,先經過DNS解析域名爲IP地址,
  2. 與WEB服務器創建TCP連接
  3. 向web服務器發送http請求,服務器響應請求,返回指定url數據
  4. 瀏覽器加載web服務器返回的數據及解析html源文件
  5. 生成DOM樹,解析css和js,渲染頁面。

數組去重

let array = [1,1,2,3,3,4,4,5,6];
let arrays = new Set(array); //es6的set語法
console.log(arrays) //1,2,3,4,5,6複製代碼

排序

降序

let abc= [2,1,5,4,3,9,7,8,10,20]
function sorts(a,b){
	return b-a; 主要區別
}
abc.sort(sorts);
console.log(abc) // [20, 10, 9, 8, 7, 5, 4, 3, 2, 1]
複製代碼

升序

let abc= [2,1,5,4,3,9,7,8,10,20]
function sorts(a,b){
	return a-b; //主要區別
}
abc.sort(sorts);
console.log(abc) // [1, 2, 3, 4, 5, 7, 8, 9, 10, 20]複製代碼

js原型和原型鏈

js原型

JS中每一個函數都存在有一個原型對象屬性prototype。而且全部函數的默認原型都是Object的實例。
css

js原型鏈

每一個繼承父函數的子函數的對象都包含一個內部屬性_proto_。該屬性包含一個指針,指向父函數的prototype。若父函數的原型對象的_proto_屬性爲再上一層函數。在此過程當中就造成了原型鏈。
html

這個知識點,能夠查看 juejin.im/post/5d0c78…es6

js數據類型

js基本數據類型

String、Number 、Boolean、Undefined、Null、Symbolweb

js引用數據類型

Object、Array、Function、Array、Data等面試

數組經常使用方法

join(): arr.join(separator) ,separator參數爲可選。將數組的元素組起一個字符串,以separator爲分隔符,省略的話則用默認用逗號爲分隔符,該方法只接收一個參數:即分隔符。數組

//不帶參數
let arr = ["掘金",6,"大地王者","奮鬥"]
console.log(arr.join());//掘金,6,大地王者,奮鬥
//帶參數
let arr = ["掘金",6,"大地王者","奮鬥"]
console.log(arr.join("-"));//掘金-6-大地王者-奮鬥複製代碼

push()和pop():push(): 能夠接收任意數量的參數,把它們逐個添加到數組末尾,並返回修改後數組的長度。 pop():數組末尾移除最後一項,減小數組的 length 值,而後返回移除的項。promise

let arr = [1];
arr.push(2,3);
console.log(arr)//[1, 2, 3]

arr2.pop();
console.log(arr2) // [1, 2]

複製代碼

shift() 和 unshift():shift():刪除原數組第一項,並返回刪除元素的值;若是數組爲空則返回undefined 。 unshift:將參數添加到原數組開頭,並返回數組的長度。列子可參考push()和pop()瀏覽器

reverse():反轉數組項的順序。bash

concat():將參數添加到原數組中。這個方法會先建立當前數組一個副本,而後將接收到的參數添加到這個副本的末尾,最後返回新構建的數組。在沒有給 concat()方法傳遞參數的狀況下,它只是複製當前數組並返回副本。此方法也能夠用於數組的合併服務器

let arr = [1,2,3]
let arr1 = arr6.concat(5,6,7)
console.log(arr1) //[1, 2, 3, 5, 6, 7]

複製代碼

slice():返回從原數組中指定開始下標到結束下標之間的項組成的新數組。slice()方法能夠接受一或兩個參數,即要返回項的起始和結束位置。在只有一個參數的狀況下, slice()方法返回從該參數指定位置開始到當前數組末尾的全部項。若是有兩個參數,該方法返回起始和結束位置之間的項——但不包括結束位置的項。

splice():能夠實現刪除、插入和替換。

刪除:能夠刪除任意數量的項,只需指定 2 個參數:要刪除的第一項的位置和要刪除的項數。例如, splice(0,2)會刪除數組中的前兩項。

插入:能夠向指定位置插入任意數量的項,只需提供 3 個參數:起始位置、 0(要刪除的項數)和要插入的項。例如,splice(2,0,4,6)會從當前數組的位置 2 開始插入4和6。


替換:能夠向指定位置插入任意數量的項,且同時刪除任意數量的項,只需指定 3 個參數:起始位置、要刪除的項數和要插入的任意數量的項。插入的項數沒必要與刪除的項數相等。例如,splice (2,1,4,6)會刪除當前數組位置 2 的項,而後再從位置 2 開始插入4和6。

splice()方法始終都會返回一個數組,該數組中包含從原始數組中刪除的項,若是沒有刪除任何項,則返回一個空數組。

map() (ES5新增):方法返回一個新數組,數組中的元素爲原始數組元素調用函數處理後的值。不會對空數組進行檢測。不會改變原始數組。參數接收的是一個方法,Array.map(callback);

const arr = [1, 3, 4, 5, 6, 7, 8, 10];
const res = arr.map((num)=>{
    return num * num; //[ 1, 9, 16, 25, 36, 49, 64, 100 ]
})
複製代碼

filter() (ES5新增):方法建立一個新的數組,新數組中的元素是經過檢查指定數組中符合條件的全部元素。數組。

var words = ['1', '2', '3', '14', '34', '56'];

const result = words.filter(word => word > 6);

console.log(result); //["14", "34", "56"]
複製代碼

every() (ES5新增):判斷數組中每一項都是否知足條件,只有全部項都知足條件,纔會返回true。

some() (ES5新增):判斷數組中是否存在知足條件的項,只要有一項知足條件,就會返回true。

有關數組的更多用法,能夠查看: developer.mozilla.org/en-US/docs/…

閉包

什麼是閉包

閉包是一個定義在一個函數(父函數)裏面的函數,它擁有對父函數裏面的變量的訪問權。

閉包注意事項

一般,函數的做用域及其全部變量都會在函數執行結束後被銷燬。可是,在建立了一個閉包之後,這個函數的做用域就會一直保存到閉包不存在爲止。

function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));  // 7
console.log(add10(2)); // 12

// 釋放對閉包的引用
add5 = null;
add10 = null;
複製代碼

閉包中的 this 對象

var name = "The Window";

var obj = {
  name: "My Object",
  
  getName: function(){
    return function(){
      return this.name;
    };
  }
};

console.log(obj.getName()());  // The Window
複製代碼

obj.getName()()其實是在全局做用域中調用了匿名函數,this指向了window。這裏要理解函數名與函數功能(或者稱函數值)是分割開的,不要認爲函數在哪裏,其內部的this就指向哪裏。匿名函數的執行環境具備全局性,所以其 this 對象一般指向 window。

閉包的應用

應用閉包的主要場合是:設計私有的方法和變量。

閉包的缺陷

閉包的缺點就是常駐內存會增大內存使用量,而且使用不當很容易形成內存泄露

來一道常考閉包面試題

function fun(n,o){
  console.log(o);
  return {
    fun: function(m){
      return fun(m,n);
    }
  };
}

var a = fun(0);  // ?
a.fun(1);        // ?        
a.fun(2);        // ?
a.fun(3);        // ?

var b = fun(0).fun(1).fun(2).fun(3);  // ?

var c = fun(0).fun(1);  // ?
c.fun(2);        // ?
c.fun(3);        // ?
複製代碼

答案

undefined
0
0
0

undefined, 0, 1, 2

undefined, 0
1
1複製代碼

實現一個簡單的Promise

function Promise(executor) {
    //executor
    this.status = 'pending'
    this.reason = null
    this.data = null
    this.onFulFilledList = []
    this.onRejectedList = []
    const _this = this;

    function resolve(data) {
        if(_this.status == 'pending') {
            _this.data = data
            _this.status = 'onFulfilled'
            _this.onFulFilledList.forEach(element => {
                element(_this.data)
            });
        }
    }

    function reject(e) {
        if(_this.status == 'pending') {
            _this.reason = e
            _this.status = 'rejected'
            _this.onRejectedList.forEach(element => {
                element(_this.reason)
            })
        }
    }

    executor(resolve, reject)
}

Promise.prototype.then = function(res, rej) {
    const _this = this
    if(_this.status=='onFulfilled') {
        res(_this.data)
        return
    }
    if(_this.status=='rejected') {
        res(_this.reason)
    }
    if(_this.status=='pending'){
        _this.onFulFilledList.push(res)
        _this.onRejectedList.push(rej)
    }
}複製代碼

面試夠用用版

function promise(constructor) {
    let self = this;
    self.status = "pending"; //定義狀態改變前的初始狀態
    self.value = undefined; //定義狀態爲resolved的時候的狀態
    self.reason = undefined; //定義狀態爲rejected的時候的狀態
    
    function resolve(value) {
        兩個==="pending",保證了狀態的改變是不可逆的
        if(self.status === 'pending') {
            self.value = value;
            self.status = "resolved"
        }
    }

    function reject(reason) {
        兩個==="pending",保證了狀態的改變是不可逆的
        if(self.status === "pending") {
            self.readon = reason;
            self.status = "rejected";
        }
    }

    //捕獲構造異常
    try{
        constructor(resolve, reject)
    }catch(e){
        reject(e)
    }
}複製代碼

同時,須要在 myPromise的原型上定義鏈式調用的 then方法:

promise.prototype.then = function(onFullfilled, onRejected) {
    let self = this;
    switch(self.status){
        case "resolved":
            onFullfilled(relf.value);
        brack;
        case "rejected":
             onRejected(self.reason);
        break;
        default:
    }
}複製代碼

new的實現原理

new關鍵字會進行以下操做

  1. 建立一個空對象,構造函數中的this指向這個空對象
  2. 連接該對象到另外一個對象(即設置該對象的__proto__爲構造函數的prototype)
  3. 執行構造函數,將構造函數內的this做用域指向1步驟中建立的空對象{}
  4. 若是構造函數有返回值,則return返回值,不然return空對象obj

根據new的操做,實現代碼

function new() {
    let obj = {} //建立一個空對象
    let [constructor, ...args] = [...arguments]
    obj.__proto__ == constructor.prototype //設置該對象的__proto__爲構造函數的prototype
    let result = constructorr.apply(obj, args) //將構造函數的做用域指向建立的空對象上
    if(result && (typeof (result) === 'object' || typeof(result) ==='function')) {
       return result //若是構造函數執行的結構返回的是一個對象,那麼返回這個對象
    }
    return obj //若是構造函數返回的不是一個對象,返回建立的新對象
}複製代碼

寫一個方法,實現sum(2,3)和sum(2)(3)可以正常工做

第一種方法

function sum(x) {
    if(arguments.length == 2) {
        return arguments[0] + arguments[1];
    }else{
        return function(y) {
            retunr x + y
        }
    }
}複製代碼

第二種方法

function sum(x,y) {
    if(y !== undefined){
        return x + y;
    }else{
        return function (y) {
            return x + y;
        }
    }
}複製代碼

防抖實現

典型例子:鼠標連擊觸發

實現原理:當一次事件發生後,事件處理器要等必定閥值的時間,若是這段時間過去後,再也沒有事件發生,就處理最後一次發生的事件

function debounce(fn, wait=50, immediate) {
    let timer;
    return function() {
        if(immediate){
            fn.apply(this, arguments)
        }
        if(timer) clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(this, arguments)
        }, wait)
    }
}複製代碼

節流實現

能夠理解爲時間再一個管道中傳輸,加上這個節流閥之後,時間的流速就會減慢,實際上這個函數的就是如此,他能夠將一個函數的調用頻率在必定閥值內,例如1s,那麼1s內這個函數必定不會被調用兩次

function throttle(fn, wait) {
    let prev = new Date();
    return function() {
        const args = arguments;
        const now =-= new Date();
        if(now - prev > wait) {
            fn.apply(this.args)
            pre = new Date();
         }
    }
}複製代碼

Session 和 Cookie 

Cookie

服務器經過Set-Cookie頭給客戶端一串字符串

客戶端每次訪問相同域名的網頁時,必須帶上這段字符串

客戶端要在一段時間內保存這個Cookie

Cookie默認在用戶關閉頁面後就失效,後臺代碼能夠任意設置Cookie的過時時間

大小大概在4kb

Session

將SessionID(隨機數)經過Cookie發給客戶端

客戶端訪問服務器時,服務器讀取SessionID

服務器有一塊內存(哈希表)保存了全部session

經過SessionID能夠獲得對應用戶的隱私信息,如:id email

這塊內存(哈希表)就是服務器上的全部session

通常來講,Session是基於Cookie來實現的

null和undefined的區別

null是一個被分配的值,設置爲null的變量意味着其無值。而undefined則是某個變量雖然聲明瞭變量,可是還沒進行過任何賦值。

相關文章
相關標籤/搜索