天天看點

我經曆的前端面試題(二)

  • 這是來自某出行類大司的一面,涼。
  • 偏Javascript基礎。

js基礎

1.基本類型有哪些

Number String Boolean Null Undefined Symbol (落下沒說)

2.Null 和 Undefined什麼差別?

參考文章:undefined與null的差別

null表示"沒有對象",即該處不應該有值。典型用法是:

(1) 作為函數的參數,表示該函數的參數不是對象。

(2) 作為對象原型鍊的終點。

undefined表示"缺少值",就是此處應該有一個值,但是還沒有定義。典型用法是:

(1)變量被聲明了,但沒有指派時,就等于undefined。

(2)  調用函數時,應該提供的參數沒有提供,該參數等于undefined。

(3)對象沒有指派的屬性,該屬性的值為undefined。

(4)函數沒有傳回值時,預設傳回undefined。

差別:

(1)定義:undefined表示一個變量沒有被聲明,或者被聲明了但沒有被指派。(比如,一個沒有傳入實參的形參變量的值為undefined。再比如,如果一個函數什麼都不傳回,則該函數預設傳回undefined;)

                     null是一個表示“沒有值”的值,是空對象引用,引用指向為空 。

(2)類型:undefined的類型(typeof)是undefined;null的類型(typeof)是object。

(3)用Number()轉化成數值:undefined為NaN ,null為0。

3.如何判斷數組類型,幾種方法?

參考文章:Js中如何判斷一個對象為數組類型

var testArr = [1, 2]

console.log (testArr instanceof Array )
console.log( testArr.constructor == Array ) // 不一定準确,因為數組是引用類型
console.log( Object.prototype.toString.call(testArr) === '[object Array]' )
console.log( Array.isArray( testArr) ) //ES5提供
           

4.循環有哪些寫法?for括号中有什麼,能不寫嗎?while的條件可以是什麼?結束循環有哪些方式?

結束循環的方法:

  • return ==》結束循環并中斷函數執行;
  • break ==》結束循環函數繼續執行;
  • continue ==》跳過本次循環;
  • for 循環中的變量 i,由于 ES5并沒有塊級作用域的存在,它在循環結束以後仍然存在于記憶體中,是以建議使用函數自執行的方式來避免;

10.周遊一個數組的方法?

(1)常用的方法性能對比(由強到弱):for(length緩存,每次計算length、不為null)、forEach、map、for of 、for in 。參考文章:JS幾種數組周遊方式以及性能分析對比(已經不知道誰是原作者了,2006年的應該是吧)

(2)我不常用的方法還有:filter、some、every、reduce、reduceRight、find、findIndex

(3)ES6提供的:entries()、keys()、values()

參考文章:js數組周遊方法總結(頁面好看點就完美了)

它們都傳回一個周遊器對象,可以用for...of循環進行周遊,唯一的差別是keys()是對鍵名的周遊、values()是對鍵值的周遊,entries()是對鍵值對的周遊。

5.ES6:let 和 var 有哪些差別?

(1)塊作用域:

let

聲明的變量僅在塊級作用域内有效,var聲明的變量在全局範圍内都有效。

(2)變量提升:

let

聲明的變量一定要在聲明後使用,否則報錯ReferenceError。

var聲明的

變量可以在聲明之前使用,值為

undefined,即

“變量提升”。

(3)let的“暫時性死區”(TDZ):如果區塊中存在

let

const

指令,這個區塊對這些指令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。使用

let

指令聲明變量之前,該變量都是不可用的。這在文法上,稱為“暫時性死區”(temporal dead zone,簡稱 TDZ)。

if (true) {
  // TDZ開始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ結束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}
           

6.ES6:箭頭函數與普通函數寫法有什麼差別?

參考文章:箭頭函數和普通函數的差別

(1)構造函數:箭頭函數沒有構造函數,不能通過new獲得對象。

(2)參數:箭頭函數不綁定arguments,取而代之用rest參數...解決

let C = (...c) => {
  console.log(arguments) // Uncaught ReferenceError: arguments is not defined
  console.log(c);
}
C(3,82,32,11323);  // [3, 82, 32, 11323]
           

(3)this指向:箭頭函數不綁定this,會捕獲其所在的上下文的this值,作為自己的this值。

(先自己分析,再看連結裡的具體分析)

示例一:

var obj = {
  a: 10,
  b: function(){
    console.log(this.a); //10
  },
  c: function() {
     return ()=>{
           console.log(this.a); //10
     }
  }
}
obj.b(); 
obj.c()();
           

示例二: 

var obj = {
  a: 10,
  b: () => {
    console.log(this.a); //undefined
    console.log(this); //window
  },
  c: function() {
    console.log(this.a); //10
    console.log(this); //obj{...}
  }
}
obj.b(); 
obj.c();
           

(4)使用call()和apply()調用:直傳入參數,不改變this指向。

(5)原型屬性:箭頭函數沒有原型屬性。

(6)箭頭函數不能當做Generator函數,不能使用yield關鍵字。

(7)箭頭函數不能換行。

7.一個頁面引入了1.js和2.js,1.js中有個變量a,2.js能通路到a變量嗎?怎麼通路?

我想到的最直接的:html中引用1.js、2.js,2.js中可以通路1.js中的方法進而通路到變量。具體怎麼寫?兩種。

方法一:構造函數。

從閉包角度,對于getName,它的作用域鍊中包括包含函數的作用域,是以能通路到name變量

<!--在html中-->
<script src="coding.js"></script>
<script src="test.js"></script> <!--引用coding.js中的變量-->
           
// coding.js中
function Person(name){
  var name = name || "noName"
  // 從閉包角度,對于getName,它的作用域鍊中包括包含函數的作用域,是以能通路到name變量
  this.getName=function(){
      return name; 
  };
  // setName同理
  this.setName=function(value){
    name=value;
  };
}
           
// test.js
var person = new Person()
console.log(person.name) // undefined
console.log(person.getName()) // noName
var person=new Person('哈哈');
console.log(person.getName());//'哈哈'
person.setName('呀呀');
console.log(person.getName());//'呀呀'
           
我經曆的前端面試題(二)

方法二:利用閉包的私有作用域。

構造函數使用函數表達式 并且不用var聲明;公共方法寫在原型鍊上;私有變量是執行個體共享的;

// coding.js
(function(){
  var name='noName';
  // 構造函數使用函數表達式,然而不用var聲明,是以是全局的
  Person=function(value){
      name = value;
  };
  // 公共方法寫在原型鍊上,都通路同樣的内部變量,是以私有變量是執行個體共享的
  Person.prototype.getName=function(){
      return name;
  };
  Person.prototype.setName=function(value){
      name=value;
  }
})();
           
// test.js
var person = new Person()
console.log('直接通路:' + person.name)
console.log('無參數通路:' + person.getName())
var person1=new Person('舊執行個體');
var person2=new Person('新執行個體');
console.log(person1.getName());
console.log(person2.getName());
           
我經曆的前端面試題(二)

方法三:使用本地存儲政策。cookie或者localStorage。(回憶一下做過的微信小程式項目)

方法四:使用參數傳遞。

這兩種方法感覺不是本題的意思,應該屬于跨頁面的資料傳遞。

參考文章:JS實作把一個頁面層資料傳遞到另一個頁面的兩種方式

8.形參和實參分别是什麼。

形參是函數定義的時候的參數。實參是調用該函數實際傳入的參數。

function add(a,b) { // a b 是形參
    return a + b
};
add(1,2); // 1 2 是實參
           

需要注意的是: 

  • 調用函數傳遞的實參與定義函數規定的形參是依次對應的
  • 超出形參數目的實參不傳遞其值。
  • 如果沒有對應的實參(實參數目少于形參數目)傳入,其值為undefined。
  • 而函數使用了形參未定義的‘字面量’,出錯:xx is not defined 。
// 關于實參、形參
function add(a, b, c){
  // console.log(arguments)
  console.log(a,b,c)
  console.log(a + b + c)
  // console.log(x) //報錯:x is not defined 
}
add(1,2,3,4)
add(1,2)
add(1,'2',3)
           
我經曆的前端面試題(二)

9.說一下作用域鍊。

看前面的總結即可。閉包為什麼會造成記憶體洩漏?

資料結構

1.什麼是平衡二叉樹?滿二叉樹?完全二叉樹?

下一篇:

設計模式

整理單獨一篇吧

用vue實作資料雙向綁定舉例子說的觀察者模式。

繼續閱讀