大廠HR面試必備ES6中的深刻淺出面試題知識點

file

ESMAScript6簡介,ES6是JavaScript語言的下一代標準,目的是讓JavaScript語言能夠寫複雜的大型應用程序,成爲企業級語言。那麼ECMAScript和JavaScript的關係究竟是什麼呢?二者有着什麼樣的聯繫?前端

JavaScript的創造者Netscape公司,將JavaScript提交給國際標準化組織ECMA,但願這種語言能夠成爲國際標準,次年,ECMA決定了瀏覽器腳本語言的標準,並稱爲ECMAScript。es6

因某些緣由,一是商標,二是這門語言制定者是ECMA,不是Netscape。ECMAScript和JavaScript的關係是前者是後者的規格,後者是前者的一種實現。算法

ES6 let和const命令編程

let命令:json

基本用法,ES6新增let命令,用來聲明變量,用法相似於var,但所聲明的變量,只在let命令所在的代碼塊內有效。設計模式

{
 let a = 10;
 var b = 1;
}

a // ReferenceError: a is not defined
b // 1

let和var聲明瞭兩個變量,而後在代碼塊以外調用這兩個變量,結果let聲明的變量報了錯,var聲明的變量返回了正確的值。說明,let聲明的變量只在它所在的代碼塊有效。數組

for(let i = 0; i<10; i++) {
}
console.log(i);
// ReferenceError: i is not defined
var a = [];
for(var i = 0; i<10; i++) {
 a[i] = function() {
  console.log(i);
 };
}
a[6](); // 10

使用let,聲明的變量僅僅在塊級做用域內有效:promise

var a = [];
for(let i = 0; i<10; i++){
 a[i] = function() {
  console.log(i);
 };
}
a[6](); // 6

變量i是let聲明的,當前的i只在本輪循環有效,因此每一次循環的i其實都是一個新的變量,因此最後輸出6。瀏覽器

不存在變量提高安全

var存在變量提高,let不會發生「變量提高」的現象,因此,變量必定要在聲明後使用,否則會報錯。

console.log(a); // 輸出undefined
console.log(b); // 報錯ReferenceError

var a = 1;
let b = 1;

var聲明的變量會發生變量提高,該變量沒用賦值就已經存在了,可是沒有值,就會輸出undefined,變量用let命令聲明,不會發生變量提高,聲明變量以前,變量是不存在的,若是用它,就會報錯。

用let聲明的變量是能夠修改的,而用const通常用來聲明常量,聲明以後不能更改了。

let a = 1;
const b = 2;
a = 3;
b = 3; // 報錯

var命令聲明的變量會發生變量提高的現象,變量在聲明以前使用,其值爲undefined,而let命令聲明的變量沒有變量提高,若是在聲明以前使用,會報錯的。

暫時性死區,在一個塊級做用域中對一個變量使用let聲明前,該變量是不可以使用,稱爲暫時性死區。

da = 'coding';
if(true) {
 // 在以前就定義 一個全局變量da,塊內從新定義了一個da
 console.log(da); // 報錯ReferenceError
 let da;
}

不容許重複聲明:

let命令是不容許重複聲明同一個變量的

if(true) {
 let da;
 let da; // 報錯
}

function func(coding) {
 // 已經有個變量名的形參了
 let coding;
}
func() // 報錯

在代碼塊內,使用let命令聲明變量以前,該變量都是不可用的,稱爲暫時性死區。

if(true) {
 temp = 'da'; // ReferenceError
 console.log(temp); // ReferenceError
 
 let temp; // TDZ結束
 console.log(temp); // undefined
 
 temp = 12;
 console.log(temp); // 12
}

暫時性死區代表typeof再也不是一個安全的操做

typeof x; // ReferenceError
let x;

變量x使用了let命令聲明,因此存在死區,用到該變量就會報錯,做爲對比,若是一個變量根本沒有被聲明,使用typeof就不會報錯

typeof dacoding // undefined

ES6:

var arr = [];
for(var i=0; i<10; i++) {
 arr.push(function() { console.log(i) })
}

arr.forEach(function(func) {
 func()
});
// ES5
var arr = [];
for(var i=0; i<10; i++){
 func.push((function(value){
  return function() {
   console.log(value);
  }
 }(i))
}
// ES6
for(let i = 0; i<10; i++) {
 func.push(function(){
  console.log(i)
 })
}

箭頭函數的特色:不須要function關鍵字來建立函數,省略return關鍵字,繼承當前上下文的this關鍵字。

let聲明變量和const聲明常量,兩個都有塊級做用域

ES5中沒有塊級做用域,var有變量提高,在let中,使用的變量必定要進行聲明。箭頭函數,定義不在使用關鍵字function(),而是用箭頭 ()=> 來表示。模板字符串,是加強版的字符串,用反引號(`)表示,能夠看成普通字符串使用,同時能夠定義多行字符串。

解構賦值,ES6容許按照必定模式,從數組和對象中提取值,對變量進行賦值,for...of循環能夠遍歷數組,set和map結構。

set數據結構相似數組同樣的,全部的數據都是惟一,沒有重複的值,它自己是一個構造函數,class類的繼承,ES6中不像ES5中使用原型鏈實現繼承,引入了class概念能夠用來繼承了

// 基礎用法
const da1 = function (參數1, 參數2, …, 參數N) { 函數聲明 }
const da1 = (參數1, 參數2, …, 參數N) => { 函數聲明 }

// 當只有一個參數時,圓括號是可選
const da2 = (單一參數) => { 函數聲明 }
const da2 = 單一參數 => { 函數聲明 }

// 沒有參數時,圓括號不能省略
const da3 = () => { 函數聲明 }

// 當函數體只是 return 一個單一表達式時,能夠省略花括號和 return 關鍵詞
const da4 = () => { return 表達式(單一) }
const da4 = () => 表達式(單一)

// 函數體返回對象字面表達式時,若是省略花括號和 return 關鍵詞,返回值須要加括號
const da5 = () => { return {foo: 'bar'} }

const da5 = () => ({foo: 'bar'})  
// 輸出 {foo: 'bar'}

const da6 = () => {foo: 'bar'}    
// 輸出 undefined,大括號被識別爲代碼塊

塊級做用域:

es5只有全局做用域和函數做用域,沒有塊級做用域:

var temp = new Date();

function f() {
  console.log(temp);
  if (false) {
    var tmp = "hello world";
  }
}

f(); // undefined

es6的塊級做用域:

function f1() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n); // 5
}
// IIFE 寫法
(function () {
  var temp = ...;
  ...
}());

// 塊級做用域寫法
{
  let temp = ...;
  ...
}

es5中,函數只能在頂層做用域和函數做用域之中聲明,不能在塊級做用域中聲明。

// 狀況一
if (true) {
  function f() {}
}

// 狀況二
try {
  function f() {}
} catch(e) {
}

// ES5的規定都是非法的
// ES5嚴格模式
'use strict';
if (true) {
  function f() {}
}
// 報錯

在es6中引入了塊級做用域,明確容許在塊級做用域之中聲明函數

// ES6嚴格模式
'use strict';
if (true) {
  function f() {}
}
// 不報錯

es6的塊級做用域聲明函數只在使用大括號的狀況下成立

// 不報錯
'use strict';
if (true) {
  function f() {}
}

// 報錯
'use strict';
if (true)
  function f() {}

箭頭函數:

用了箭頭函數,this就不是在指向window,而是父級了,不可以使用arguments對象了,不能用構造函數了,就是不能使用new命令了,不然會報錯,不能使用yield命令,因此箭頭函數不能用做Generator函數了。

map和set的區別:

set用於數據重組,map用於數據儲存

set中元素不能重複,只有鍵值沒有鍵名,相似數組,能夠遍歷,有方法add,delete,has等。

map的本質是鍵值對的集合,能夠遍歷,能夠跟各類數據轉換。

class類的出現:

//定義類
class Point { 
  constructor(x,y) { 
      //構造方法
       this.x = x; //this關鍵字表明實例對象
       this.y = y; 
  } 
  toString() {
       return '(' + this.x + ',' + this.y + ')'; 
  }
}

promise構造函數是同步執行的,then方法是異步執行的。

function Person(){
  this.age = 10;

  setInterval(() => {
    this.age++;    // this 正確地指向 p 實例
  }, 100);
}

var p = new Person();  // 1s後打印出 10
this.param = 1

const func1 = () => console.log(this.param)

const func2 = function() {
    console.log(this.param)
}

func1.apply({ param: 2 })   // 輸出: 1
func2.apply({ param: 2 })   // 輸出: 2

解構賦值:

let [a, b, c] = [1, 2, 3]          
// a:1 b:2 c:3

let [a, [[b], c]] = [1, [[2], 3]]  
// a:1 b:2 c:3

let [a, , b] = [1, 2, 3]           
// a:1 b:3

let [a,...b] = [1, 2, 3]           
// a:1 b:[2, 3]

let [a, b,...c] = [1]              
// a:1 b:undefined c:[]

let [a, b = 4] = [null, undefined] 
// a:null b:4

let [a, b = 4] = [1]               
// a:1 b:4

let [a, b = 4] = [1, null]         
// a:1 b:null

解構不成功的,其變量的值爲undefined,解構指定默認值,若是該被解構變量的對應位置沒有值,爲空或者是undefined,默認值纔有效。

let { a, b } = { a: 1, b: 2 }      
// a:1 b:2

let { c } = { a: 1, b: 2 }         
// c:undefined

let { c = 4 } = { a: 1, b: 2 }     
// c:4

let { a: c } = { a: 1, b: 2 }      
// c:1

let { a: c = 4, d: e = 5 } = { a: 1, b: 2 }   
// c:1 e:5

let { length } = [1, 2]            
// length:2

擴展運算符:

將一個數組轉化爲逗號分隔的參數序列

console.log(...[1, 2, 3])               
// 1 2 3

console.log(1, ...[2, 3, 4], 5)         
// 1 2 3 4 5

[...document.querySelectorAll('div')]   
// [<div>, <div>, <div>]

{...{a: 1}, ...{a: 2, b: 3}}            
// {a: 2, b: 3}

[...[1], ...[2, 3]]                     
// [1, 2, 3]

const arr = [1]
arr.push(...[2, 3])                     
// arr:[1, 2, 3

默認參數:

function log(x, y = 'World') {
    console.log(x, y)
}

log('Hello')             
// Hello World

log('Hello', undefined)  
// Hello World

log('Hello', 'China')    
// Hello China

log(undefined, 'China')  
// undefined China

log(, 'China')           
// 報錯 SyntaxError

log('Hello', '')         
// Hello

log('Hello', null)       
// Hello null

參數不傳遞或是傳遞undefined會讓參數等於默認值,若是參數不是最後一個,不傳遞參數就會報錯。

傳遞null不會讓函數參數等於默認值。

// 獲取函數全部的參數,rest 爲數組
function func1(...rest){ /* ... */}

// 獲取函數第一個參數外其餘的參數,rest 爲數組
function func1(val, ...rest){ /* ... */}

模板字符串:

var str = `abc
def
gh`;
console.log(str);
let name = "小明";
function a() {
    return "ming";
}
console.log(`個人名字叫作${name},年齡${17+2}歲,性別${'男'},遊戲ID:${a()}`);

函數的默認參數:

function A(a,b=1){
    console.log(a+b);
}
A(1);    //2
A(2+3);  //5
function A(a,b=1){
    console.log(a+b);
}
A(1);    //2
A(2+3);  //5

箭頭函數:

//省略寫法
var people = name => 'hello' + name;
 
var getFullName = (firstName, lastName) => {
    var fullName = firstName + lastName;
    return fullName;
}

對象的擴展:

var foo = 'bar';
var baz = {foo};  
//等同於  var baz = {foo: foo};
var o = {
  method() {
    return "Hello!";
  }
};
 
// 等同於
var o = {
  method: function() {
    return "Hello!";
  }
};

Promise對象

它有三種狀態,分別是pending-進行中、resolved-已完成、rejected-已失敗。

var promise = new Promise((resolve, reject) => {
    var success = true;
    if (success) {
        resolve('成功');
    } else {
        reject('失敗');
    }
}).then(
    (data) => { console.log(data)},
    (data) => { console.log(data)}
)

set數據結構

size 數據的長度
add() 添加某個值,返回 Set 結構自己。
delete() 刪除某個值,返回一個布爾值,表示刪除是否成功。
has() 查找某條數據,返回一個布爾值。
clear() 清除全部成員,沒有返回值。

Spread Operator 展開運算符(...)

將字符串轉成數組

var str="abcd";
console.log([...str]) // ["a", "b", "c", "d"]

將集合轉成數組

var set = new Set([1,2,3,4,5])
console.log([...set]) // [1, 2, 3, 4, 5]

數組的合併

var a1=[1,2,3];
var a2=[4,5,6];

console.log([...a1,...a2]); 
//[1, 2, 3, 4, 5, 6]

rest參數 …變量名稱

function func(...args){
    console.log(args);
    //[1, 2, 3, 4]
}
func(1, 2, 3, 4);
 
function f(x, ...y) {
    console.log(x);
    console.log(y);
}

f('a', 'b', 'c');     //a 和 ["b","c"]
f('a')                //a 和 []
f()                   //undefined 和 []

經典

var val = "全局變量";

{
  let val = "局部變量";
  console.log(val);     
  // 局部變量
}

console.log(val);       
// 全局變量

const val = "常量";
val = "123";            
// Uncaught TypeError: Assignment to constant variable.

迭代器iterator、for...of和for...in

//for in 會繼承
for (let i in iterable) {
    console.log(i); 
    // 依次打印 0, 1, 2, "foo", "arrCustom", "objCustom"
}

for (let i in iterable) {
    if (iterable.hasOwnProperty(i)) {
        console.log(i); 
        // 依次打印 0, 1, 2, "foo"
    }
}

// for of
for (let i of iterable) {
    console.log(i); 
    // 依次打印 3, 5, 9
}

forEach,for in,for of三者區別:

forEach來遍歷數組,for in 遍歷對象或json,for of數組對象均可以遍歷,for in 循環出的是key,for of 循環出的是value。

const promise = new Promise((resolve, reject) => {
    console.log(1);
    resolve();
    console.log(2);
})

promise.then(() => {
    console.log(3);
})

console.log(4);
1 2 4 3

Promise.then() 內部的代碼在 當次 事件循環的 結尾 馬上執行

關於目前文章內容即涉及前端,PHP知識點,若是有興趣便可關注,很榮幸,能被您發現,真是慧眼識英!也感謝您的關注,在將來的日子裏,但願可以一直默默的支持我,我也會努力寫出更多優秀的做品。咱們一塊兒成長,從零基礎學編程,將 Web前端領域、數據結構與算法、網絡原理等通俗易懂的呈現給小夥伴。分享 Web 前端相關的技術文章、工具資源、精選課程、熱點資訊。

推薦閱讀

一、你知道多少this,new,bind,call,apply?那我告訴你

二、爲何學習JavaScript設計模式,由於它是核心

三、一篇文章把你帶入到JavaScript中的閉包與高級函數


意見反饋:
若本號內容有作得不到位的地方(好比:涉及版權或其餘問題),請及時聯繫咱們進行整改便可,會在第一時間進行處理。


感謝閱讀,原創不易,喜歡就點個贊吧,這是我寫做最大的動力。

歡迎關注達達的簡書!

這是一個有質量,有態度的博客

博客

相關文章
相關標籤/搜索