前端面試題總結(陸續更新.......)

chaos_G發表於2019-12-09

1.let const var 的區別

在JavaScript中,有三個關鍵字可用於宣告一個變數,並且每個關鍵字都有其不同之處。分別var,let和const。一個簡單粗暴的解釋:使用const關鍵字宣告的變數不能被重新賦值,let而且var可以。也可以這麼說:const只可以宣告一個常量(js中一旦被定義就無法再被修改的變數,稱之為常量)。

eg:

const name = '小明'
console.log(name)
name = '小藍' //can't be reassigned


let name = "小明";
person = "小藍";
console.log(person); //  reassignment is allowed with let

複製程式碼

當然有朋友提出來const定義的引用型別的值,可以進行修改

前端面試題總結(陸續更新.......)

前端面試題總結(陸續更新.......)
因為物件是引用型別的,變數中儲存的僅是物件的指標,這就意味著,const僅保證指標不發生改變,修改物件的屬性不會改變物件的指標,所以是被允許的。也就是說const定義的引用型別只要指標不發生改變,其他的不論如何改變都是允許的。 var宣告的變數是函式作用域的,這意味著當在函式中建立變數時,該函式中的所有內容都可以訪問該變數。此外,函式中建立的函式作用域變數不能在此函式之外訪問。

function myFunction() {
  var name = "小明";
  console.log(myVar); // 可以列印出來
}
console.log(name); // Throws a ReferenceError, name is not accessible outside the function.


function myFunction() {
  var myVar = "Nick";
  if (true) {
    var myVar = "John"; //此處會變數提升
    console.log(myVar); // "John"
    // actually, myVar being function scoped, we just erased the previous myVar value "Nick" for "John"
  }
  console.log(myVar); // "John" - see how the instructions in the if block affected this value
}
console.log(myVar); // Throws a ReferenceError, myVar is not accessible outside the function.

複製程式碼

var和let大致相同,但let宣告的變數是塊範圍不存在變數提升不能在同一範圍內重新宣告

function myFunction() {
  var myVar = "Nick";
  if (true) {
    let myVar2 = "John";
    console.log(myVar); // "Nick"
  }
  console.log(myVar2); //無法訪問if塊級作用域中的變數myVar2
}
console.log(myVar); //函式外部無法訪問函式內部定義的變數
複製程式碼

不能重複宣告一個let變數

let name = 'Tom';
let name = 'Bob';  //丟擲語法錯誤
複製程式碼

暫時性死區 : let不像var那樣會發生“變數提升”現象。所以,變數一定要在宣告後使用,否則報錯。

// var 的情況
console.log(foo); // 輸出undefined
var foo = 2;

// let 的情況
console.log(bar); // 報錯ReferenceError
let bar = 2;
-------------------------------------------------------------------------
console.log(foo); // 輸出undefined
console.log(bar); // 報錯ReferenceError

var foo = 2;
let bar = 2;

複製程式碼

2.ES6之箭頭函式

首先了解一下基本函式的寫法

function test(name) {  //宣告式寫法
    console.log(name)
}
test('Jerry')

let test2 = function(name) {  //賦值式寫法
    console.log(name)
}
test2('Tom')

複製程式碼

箭頭函式的基本用法

let func = value => value;
複製程式碼

相當於

let func = function (value) {
    return value;
};
複製程式碼

多個引數的箭頭函式

let func = (value, num) => value * num;
複製程式碼

相當於

let func = (value, num) => {
    return value * num
};

複製程式碼

箭頭函式的寫法:

1.箭頭函式只能用賦值式寫法,不能用宣告式寫法

2.如果引數只有一個,可以不加括號,如果沒有引數或者引數多於一個就需要加括號

3.如果函式體只有一句話,可以不加花括號

4.如果函式體沒有括號,可以不寫return,箭頭函式會幫你return

-------------------------------------------------------------------------

2.1箭頭函式的this的指向問題

箭頭函式:出現的作用除了讓函式的書寫變得很簡潔,可讀性很好外;最大的優點是解決了this執行環境所造成的一些問題。比如:解決了匿名函式this指向的問題(匿名函式的執行環境具有全域性性),包括setTimeout和setInterval中使用this所造成的問題。

2,我們常見的window屬性和方法有alter,document,parseInt,setTimeout,setInterval,localtion等等,這些在預設的情況下是省略了window字首的。(window.alter = alter)。

3,在“use strict”嚴格模式下,沒有直接的掛載者(或稱呼叫者)的函式中this是指向window,這是約定俗成的。在“use strict”嚴格模式下,沒有直接的掛載者的話,this預設為undefined。以下都是在非嚴格模式下討論。

普通函式中的this 普通函式,this的概念是:this是JavaScript的一個關鍵字,他是指函式執行過程中,自動生成的一個內部物件,是指當前的物件,只在當前函式內部使用。(this物件是在執行時基於函式的執行環境繫結的:在全域性函式中,this指向的是window;當函式被作為某個物件的方法呼叫時,this就等於那個物件)。

前端面試題總結(陸續更新.......)
這種情況下,我們希望在每一次迴圈後都能得到$("#content")的this,但是因為this是隻在當前函式內部使用的,又因為js函式是可以多層巢狀的原因,使得我們無法得到最開始的this,這時我們可以把他先用一個變數儲存起來,最終達到我們想要的目的。(一般我們會這樣定義:var _this = this   var that=this)

前端面試題總結(陸續更新.......)
列印是結果是the window。原因是,匿名函式的執行環境是全域性的,而且this只在函式內部起作用。此時的this.name在匿名函式中找不到,所以就從全域性中找,找到後列印出來。

前端面試題總結(陸續更新.......)
此時可以用一個變數儲存當前的this,此時的this就指向的是當前的物件object

es6箭頭函式的this

箭頭函式的this定義:箭頭函式的this是在定義函式時繫結的,不是在執行過程中繫結的。簡單的說,函式在定義時,this就繼承了定義函式的物件。

所以,這會很好的解決匿名函式和setTimeout和setInterval的this指向問題。我們不用再去給其用that變數儲存this。

前端面試題總結(陸續更新.......)
此時的this就是函式在哪裡定義的,this就繫結給誰

3. link與@import的區別

1.@import是CSS提供的語法規則,只有匯入樣式表的作用;link是HTML提供的標籤,不僅可以載入 CSS 檔案,還可以定義 RSS,Rel連線屬性,設定瀏覽器資源提示符preload、prefetch等。

2.HTML文件在解析的過程當中,如果遇到link標籤,則會立即發起獲取CSS檔案資源的請求;@import引入的CSS將在頁面載入完畢後才會被載入。

3@import是CSS2.1才有的語法,因此需要IE5以上才能識別;link標籤作為HTML元素,不存在相容性問題。

4. js陣列中的find、filter、forEach、map四個方法的詳解和應用例項

find():返回通過測試的陣列的第一個元素的值

在第一次呼叫 callback 函式時會確定元素的索引範圍,因此在 find 方法開始執行之後新增到陣列的新元素將不會被 callback 函式訪問到。如果陣列中一個尚未被callback函式訪問到的元素的值被callback函式所改變,那麼當callback函式訪問到它時,它的值是將是根據它在陣列中的索引所訪問到的當前值。被刪除的元素仍舊會被訪問到。

array.find(function(value, index, arr),thisValue)
複製程式碼

value:必須,代表當前元素,其他四個引數都是可選,index代表當前索引值,arr代表當前的陣列,thisValue代表傳遞給函式的值,一般用this值,如果這個引數為空,undefined會傳遞給this值

返回值:返回符合測試條件的第一個陣列元素的值,如果沒有符合條件的則返回undefined。

var arr = [1,2,3,4,5,6,7];
 var ar = arr.find(function(elem){
     return elem>5;
 });
 console.log(ar);//6
console.log(arr);//[1,2,3,4,5,6,7]
複製程式碼

find()方法為陣列中的每個元素都呼叫一次函式執行,當陣列中的元素在測試條件時返回true,find()返回符合條件的元素,之後的值不會再執行函式。如果沒有符合條件的元素則返回undefined。

filter():建立一個新陣列,新陣列中的元素是通過檢查指定陣列中符合條件的所有元素

filter 遍歷的元素範圍在第一次呼叫 callback 之前就已經確定了。在呼叫 filter 之後被新增到陣列中的元素不會被 filter 遍歷到。如果已經存在的元素被改變了,則他們傳入 callback 的值是 filter 遍歷到它們那一刻的值。被刪除或從來未被賦值的元素不會被遍歷到。

array.filter(function(value, index, arr),thisValue)

value:必須,代表當前元素,其他四個引數都是可選,index代表當前索引值,arr代表當前的陣列,thisValue代表傳遞給函式的值,一般用this值,如果這個引數為空,undefined會傳遞給this值

返回值:返回陣列,包含了符合條件的所有元素,如果沒有符合條件的則返回空陣列

var arr = [1,2,3,4,5,6,7];
 var ar = arr.filter(function(elem){
    return elem>5;
 });
console.log(ar);//[6,7]  返回一個新陣列
console.log(arr);//[1,2,3,4,5,6,7]

複製程式碼

map():返回一個新陣列,陣列中的元素為原始陣列元素呼叫函式處理後的值,map()方法按照原始陣列元素順序依次處理元素

map方法會給原陣列中的每個元素都按順序呼叫一次callback函式,callback每次執行後的返回值(包括undefined)組合起來形成一個新陣列。callback函式只會在有值的索引上被呼叫,那些從來沒被賦過值或者使用delete刪除的索引則不會被呼叫。

使用map方法處理陣列時,陣列元素的範圍是在callback方法第一次呼叫之前就已經確定了。在map方法執行的過程中,原陣列中新增加的元素將不會被callback訪問到,若已經存在的元素被改變或刪除了,則他們傳遞到callback的值是map方法遍歷到他們的那一刻的值,而被刪除的元素將不會被訪問到。

array.map(function(value, index, arr),thisValue)

複製程式碼

value:必須,代表當前元素,其他四個引數都是可選,index代表當前索引值,arr代表當前的陣列,thisValue代表傳遞給函式的值,一般用this值,如果這個引數為空,undefined會傳遞給this值

返回值:返回一個新陣列,陣列中的元素為原始陣列元素呼叫函式處理後的值

var arr = [1,2,3,4,5,6,7];
 var ar = arr.map(function(elem){
    return elem*4;
 });
 console.log(ar);//[4, 8, 12, 16, 20, 24, 28]   返回一個新陣列
console.log(arr);//[1,2,3,4,5,6,7]
複製程式碼

forEach():用於呼叫陣列每個元素,並將元素傳遞給回撥函式(注意沒有辦法跳出或終止forEach語句,除非丟擲異常)

forEach 遍歷的範圍在第一次呼叫 callback 前就會確定。呼叫forEach 後新增到陣列中的項不會被 callback 訪問到。如果已經存在的值被改變,則傳遞給 callback 的值是 forEach 遍歷到他們那一刻的值。已刪除的項不會被遍歷到

array.forEach(function(value, index, arr),thisValue)
複製程式碼

value:必須,代表當前元素,其他四個引數都是可選,index代表當前索引值,arr代表當前的陣列,thisValue代表傳遞給函式的值,一般用this值,如果這個引數為空,undefined會傳遞給this值

var arr = [1,2,3,4,5,6,7];
 var sum = 0;
 var ar = arr.forEach(function(elem){
    sum+=elem*4;
 });
 console.log(ar);//undefined
 console.log(arr);//[1,2,3,4,5,6,7]
 console.log(sum);//112

複製程式碼

forEach()返回值為undefined,裡面即便有return語句,返回值依然是undefined

現在說說各自的意義:

1.find()方法主要用來返回陣列中符合條件的第一個元素(沒有的話,返回undefined)

2.filter()方法主要用來篩選陣列中符合條件的所有元素,並且放在一個新陣列中,如果沒有,返回一個空陣列

3.map()方法主要用來對陣列中的元素呼叫函式進行處理,並且把處理結果放在一個新陣列中返回(如果沒有返回值,新陣列中的每一個元素都為undefined)

4.forEach()方法也是用於對陣列中的每一個元素執行一次回撥函式,但它沒有返回值(或者說它的返回值為undefined,即便我們在回撥函式中寫了return語句,返回值依然為undefined)

5.JS 中深拷貝的幾種實現方法

1.使用遞迴的方式實現深拷貝

//使用遞迴的方式實現陣列、物件的深拷貝
function deepClone1(obj) {
  //判斷拷貝的要進行深拷貝的是陣列還是物件,是陣列的話進行陣列拷貝,物件的話進行物件拷貝
  var objClone = Array.isArray(obj) ? [] : {};
  //進行深拷貝的不能為空,並且是物件或者是
  if (obj && typeof obj === "object") {
    for (key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (obj[key] && typeof obj[key] === "object") {
          objClone[key] = deepClone1(obj[key]);
        } else {
          objClone[key] = obj[key];
        }
      }
    }
  }
  return objClone;
}
複製程式碼

2.通過 JSON 物件實現深拷貝

//通過js的內建物件JSON來進行陣列物件的深拷貝
function deepClone2(obj) {
  var _obj = JSON.stringify(obj),
    objClone = JSON.parse(_obj);
  return objClone;
}
複製程式碼

3.通過jQuery的extend方法實現深拷貝

var array = [1,2,3,4];
var newArray = $.extend(true,[],array);
複製程式碼

4.lodash函式庫實現深拷貝

lodash很熱門的函式庫,提供了 lodash.cloneDeep()實現深拷貝
https://www.lodashjs.com/
複製程式碼

相關文章