JS基礎知識(覆蓋JS基礎面試題)

石燕平發表於2018-06-26

總結一些前端基礎的知識,有些知識可能在前端面試的時候會問到,所以做個記錄,也有助於其他人檢視,如果有什麼問題,可以指出,會積極修正。

變數型別和計算

JS中typeof的型別有哪些

    console.log(typeof undefined);  //undefined
    console.log(typeof 123);  //number
    console.log(typeof '123');  //string
    console.log(typeof true); //boolean
    console.log(typeof [1,2,3]);  //object
    console.log(typeof {"id": 11}); //object
    console.log(typeof null); //object
    console.log(typeof console.log);  //function
複製程式碼

型別轉換

  • 顯式型別轉換
    • Number 函式
      • 數字:轉換後還是數字
      • 字串:如果可以被解析為數值,則為相應的數值,如果不能,則是 NaN,如果是空字串那就是0
      • 布林值:true為1,false為0
      • undefined:NaN
      • null:0
      • object:先執行valueOf,看是否能轉換,如果不可以再執行toString,看是否可以轉換,如果不可以報錯
    • String 函式
      • 數字:轉換成對應的字串
      • 字串:還是對應的字串
      • 布林值:true為'true',false為'false'
      • undefined:undefined
      • null:null
      • object:先執行toString,看是否能轉換,如果不可以再執行valueOf,看是否可以轉換,如果不可以報錯
    • Boolean
      下面這幾個是false,其他都是true
      • NaN
      • null
      • undefined
      • 0
      • ""
      • false
  • 隱式型別轉換
    • 四則運算
    • 判斷語句
  • 奇葩的型別轉換面試題
    JS基礎知識(覆蓋JS基礎面試題)

何時使用==,何時使用===

除了obj.a == null以外,都用=====要用的時候一定要是已經定義的
obj.a == null 轉換之後其實是 obj.a == null || obj.a == undefined

JS中有哪些內建函式

    Object
    Array
    Boolean
    Number
    String
    Function
    Date
    RegExp
    Error
複製程式碼

JS變數按照儲存方式有哪些型別

  • 1.值型別
  • 2.引用型別(節省空間,公用記憶體塊)

區別:值型別改變一個不會影響其他的,引用型別改變都改變,因為公用記憶體塊

如何理解JSON

JSON是JS的一個物件,也是一種資料格式,JSON中的兩個api如下

  1. 將JSON字串轉換成JSON物件 JSON.parse()
  2. 將JSON物件轉換成JSON字串 JSON.stringify()

使用Object.prototype.toString獲取一個物件的型別

var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
toString.call(/s/); // [object RegExp]
toString.call([]); // [object Array]

//Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
複製程式碼

原型和原型鏈

原型的五條規則

  1. 所有的引用型別都可以自定義新增屬性
  2. 所有的引用型別都有自己的隱式原型(proto
  3. 函式都有自己的顯式原型(prototype)
  4. 所有的引用型別的隱式原型都指向對應建構函式的顯示原型
  5. 使用引用型別的某個自定義屬性時,如果沒有這個屬性,會去該引用型別的__proto__(也就是對應建構函式的prototype)中去找

原型鏈.png

如何準確判斷一個變數是陣列型別

arr instanceof Array

instanceof判斷一個引用型別是什麼引用型別,是通過__proto__(隱式原型一層一層往上找,能否找到對應建構函式的prototype)

寫一個原型鏈繼承的例子

function Element(ele) {
  this.ele = document.getElementById(ele);
}

Element.prototype.html = function(val) {
  var ele = this.ele;
  if (val) {
    ele.innerHTML = val;
    return this;
  } else {
    return ele.innerHTML;
  }
};

Element.prototype.on = function(type, fn) {
  var ele = this.ele;
  ele.addEventListener(type, fn);
  return this;
}

var element = new Element('main');

element.html('hello').on('click', function() {
  alert('handleClick');
});
複製程式碼

描述new一個物件的過程

  1. 建立一個新物件
  2. this指向這個新物件
  3. 執行程式碼給this賦值
  4. return this
function Foo(name) {
  this.name = name;
  // return this;  // 本身會執行這一步
}

var f = new Foo('shiyanping');
複製程式碼

作用域及閉包

變數提升

以下兩種情況會進行提升:

  1. 變數定義
  2. 函式說明

this幾種不同的使用場景

  1. 在建構函式中使用(建構函式本身)
  2. 作為物件屬性時使用(呼叫屬性的物件)
  3. 作為普通函式時使用(window)
  4. call,apply,bind(執行的第一個引數)
var a = {
  name: 'A',
  fun: function() {
    console.log(this.name);
  }
};

a.fun();  //this === a
a.fun.call({ name: 'B' });  //this === { name: 'B' }
var fun1 = a.fun;
fun1(); //this === window
複製程式碼

建立10個a標籤,點選每個彈出對應的序號

var i;
for (i = 0; i < 10; i++) {
  (function(i) {
    // 函式作用域
    var a = document.createElement('a');
    a.innerHTML = i + '<br>';
    a.addEventListener('click', function(e) {
      e.preventDefault();
      alert(i);
    });
    document.body.appendChild(a);
  })(i);
}
複製程式碼

如何理解作用域

  1. 自由變數
  2. 作用域鏈,及自由變數的查詢,找不到逐級向上找
  3. 閉包的兩個場景
    1. 函式作為變數傳遞
    2. 函式作為返回值

實際開發中閉包的應用

// 判斷一個數字是否出現過
function isFirst() {
  var _list = [];
  return function(id) {
    if (_list.indexOf(id) >= 0) {
      return false;
    } else {
      _list.push(id);
      return true;
    }
  };
}

var first = isFirst();
first(10);
first(10);
first(20);
複製程式碼

單執行緒和非同步

同步和非同步的區別,分別列舉一個同步和非同步的例子

同步會阻塞程式碼,但是非同步不會 alert是同步 setTimeout是非同步

關於setTimeout的筆試題

console.log(1);
setTimeout(function() {
  console.log(2);
}, 0);
console.log(3);
setTimeout(function() {
  console.log(4);
}, 1000);
console.log(5);
// 輸出結果:1,3,5,2,4
複製程式碼

前端使用非同步的場景

  1. 定時任務:setTimeout,setInterval
  2. 網路請求:ajax請求,動態img載入
  3. 事件繫結

需要等待的情況下都需要非同步,因為不會像同步一樣阻塞

日期和Math

知識點:

日期

console.log(Date.now());  // 獲取當前毫秒數
var dt = new Date();  // 獲取當前時間
console.log(dt.getTime());  // 當前時間的毫秒數
console.log(dt.getFullYear());  //  年
console.log(dt.getMonth()+1); // 月(0-11)
console.log(dt.getDate());  // 日(0-31)
console.log(dt.getHours()); // 時(0-23)
console.log(dt.getMinutes()); // 分(0-59)
console.log(dt.getSeconds()); // 秒(0-59)
複製程式碼

Math

  • Math.random() - 返回 0 ~ 1 之間的隨機數
  • Math.abs(x) - 返回數的絕對值
  • Math.ceil(x) - 向上取整
  • Math.floor(x) - 向下取整

常用的陣列api

  • forEach(遍歷所有元素)
var arr = ['a', 'b', 'c', 'd'];
arr.forEach(function (item, index) {
  console.log(item + ',' + index);
})
複製程式碼
  • map(對陣列進行重新組裝,生成新的陣列)
// map,生成新陣列,不改變原來陣列的格式
var arr = ['a', 'b', 'c', 'd'];
var result = arr.map(function (item, index) {
  return index + '/' + item;
})
console.log(result);
複製程式碼
  • sort(對陣列進行排序)
// sort, 會改變原來陣列
var arr = [1, 23, 3, 4];
var result = arr.sort(function (a, b) {
  // 從小到大排序
  return a - b;

  // 從大到小排序
  // return b - a;
})
console.log(result);
複製程式碼
  • filter(過濾符合條件的元素)
var arr = [1, 2, 3, 4];
var result = arr.filter(function (item, index) {
  if (item < 3) {
    return true
  }
})
console.log(result);
複製程式碼
  • every(判斷所有元素是否都符合要求)
var arr = [1, 2, 3, 4];
var result = arr.every(function (item, index) {
  if (item < 3) {
    return true
  }
})
console.log(result);   // false
複製程式碼
  • some(判斷是否有至少一個元素符合條件)
var arr = [1, 2, 3, 4];
var result = arr.some(function (item, index) {
  if (item < 3) {
    return true
  }
})
console.log(result);  // true
複製程式碼
  • join(根據條件對陣列組合成字串)
var arr = [1, 2, 3, 4];
var result = arr.join(',');
console.log(result);
複製程式碼
  • reverse(將陣列反轉)
var arr = [1, 2, 3, 4];
var result = arr.reverse();
console.log(result);
複製程式碼

常用的物件api

  • for in
  • hasOwnProperty(檢查屬性是不是物件自有的,排除從原型鏈找到的屬性)
 var obj = {
  x: 10,
  y: 20,
  z: 30
}

for (var key in obj) {
  if (obj.hasOwnProperty(key)) {
    console.log(key + ':' + obj[key]);
  }
}
複製程式碼

問題:

獲取當前日期

function formatDate(dt) {
  if (!dt) {
    dt = new Date();
  }
  var year = dt.getFullYear();
  var month = dt.getMonth() + 1;
  var date = dt.getDate();

  if (month < 10) {
    month = '0' + month;
  }

  if (date < 10) {
    date = '0' + date;
  }

  return year + '-' + month + '-' + date;
}

var nowDate = new Date();
var formatDate = formatDate(nowDate);
console.log(formatDate);
複製程式碼

獲取隨機數,要求長度一致的字串格式

function randomStr(len) {
  var random = Math.random();
  random = random + '0000000000'; // 防止自動生成的數字不滿足長度報錯並且強制轉換成字串
  return random.substr(0, len)
}

console.log(randomStr(20));
複製程式碼

寫一個能遍歷物件和陣列的通用forEach函式

function forEach(obj, fn) {
  if (obj instanceof Array) {
    obj.forEach(function (item, index) {
      fn(index, item);
    })
  } else {
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        fn(key, obj[key]);
      }
    }
  }
}

var arr = [1, 2, 3, 4];
forEach(arr, function (index, item) {
  console.log(index + ',' + item);
});

var obj = {
  x: 10,
  y: 20
};
forEach(obj, function (index, item) {
  console.log(index + ',' + item);
});
複製程式碼

後續還在持續更新中

相關文章