面试宝典之ES6知识点

前言

在现代 JavaScript 开发中,ECMAScript 6(ES6)已经成为了开发者们的标配,它引入了许多令人期待的语言特性,使得JavaScript的编程体验更加强大、灵活和现代化。对于准备面试或提升自身技能的开发者而言,熟练掌握ES6是至关重要的一环。

本篇面试宝典将深入剖析ES6中的关键知识点,涵盖了箭头函数、解构赋值、let 和 const、Promise、模板字符串、类与继承、模块化等重要概念。我们将通过简单易懂的例子、清晰的解释,帮助你更好地理解和掌握 ES6 的精髓,为你在面试时的表现提供有力的支持。

无论你是初学者还是经验丰富的开发者,这份宝典都将为你提供深入浅出的ES6学习之路,助你在JavaScript的世界中游刃有余。让我们一同探索ES6的奥秘,迎接更高级别的JavaScript开发挑战!

1. var、let 及 const 区别

首先,我们来了解提升(hoisting)的概念。在使用var声明变量时,存在提升的情况。例如:

console.log(a); // undefined
var a = 1;

这是因为变量声明被提升,实际执行时相当于:

var a;
console.log(a); // undefined
a = 1;

对于let const,它们引入了块级作用域,解决了var的一些问题。使用letconst声明的变量不会在声明前被访问,存在暂时性死区。例如:

console.log(b); // ReferenceError: b is not defined
let b = 2;

另外,letconst不会像var一样将变量挂载到全局对象上,而是在块级作用域内有效。同时,使用const声明的变量不能再次赋值。

涉及面试题:
  • 什么是提升?
  • 什么是暂时性死区?
  • varletconst 区别?

2. 原型继承和 Class 继承

JavaScript中,虽然有class语法,但本质上并不存在类,class 只是语法糖,其背后仍然是基于原型的继承。

2.1 原型继承

组合继承是最常用的继承方式:

function Parent(value) {
  this.val = value;
}

Parent.prototype.getValue = function() {
  console.log(this.val);
};

function Child(value) {
  Parent.call(this, value);
}

Child.prototype = new Parent();

const child = new Child(1);

child.getValue(); // 1
console.log(child instanceof Parent); // true

组合继承通过在子类构造函数中调用父类构造函数,并通过改变子类的原型为父类的实例来实现继承。但这样会导致子类原型上多了不需要的父类属性,存在内存上的浪费。

2.2 Class 继承

ES6 引入了class语法,使得继承更加直观和易用:

class Parent {
  constructor(value) {
    this.val = value;
  }

  getValue() {
    console.log(this.val);
  }
}

class Child extends Parent {
  constructor(value) {
    super(value);
  }
}

const child = new Child(1);

child.getValue(); // 1
console.log(child instanceof Parent); // true

class 实际上是在原型基础上的一层封装,它使得继承更加直观。

涉及面试题:
  • 原型如何实现继承?
  • Class 如何实现继承?
  • Class 本质是什么?

3. 模块化

使用模块化可以解决命名冲突、提高代码复用性和可维护性的问题。在早期,立即执行函数是实现模块化的一种常见方式:

(function(globalVariable){
   globalVariable.test = function() {}
   // ... 声明各种变量、函数都不会污染全局作用域
})(globalVariable);

此外,AMD CMD 也是模块化的方案,而在Node.js中,CommonJS 是常见的模块管理方式:

// CommonJS
// a.js
module.exports = {
    a: 1
}
// or 
exports.a = 1

// b.js
var module = require('./a.js')
console.log(module.a); // log 1

ES6 引入了原生的模块化方案:

// ES Module
// a.js
export const a = 1;

// b.js
import { a } from './a.js';
console.log(a); // 1

涉及面试题:

  • 模块化的优势是什么?
3.1 立即执行函数

在早期的JavaScript中,使用立即执行函数实现模块化是一种常见的手段。通过函数作用域,解决了命名冲突和全局污染的问题:

(function(globalVariable){
   globalVariable.test = function() {}
   // ... 声明各种变量、函数都不会污染全局作用域
})(globalVariable);
涉及面试题:
  • 立即执行函数的作用是什么?
3.2 AMD 和 CMD

虽然 AMD(Asynchronous Module Definition)CMD(Common Module Definition)已经相对较少使用,但了解它们的特性也是必要的。它们是用于浏览器端模块化的方案。

// AMD
define(['./a', './b'], function(a, b) {
  // 加载模块完毕可以使用
  a.do();
  b.do();
});
// CMD
define(function(require, exports, module) {
  // 加载模块
  // 可以把 require 写在函数体的任意地方实现延迟加载
  var a = require('./a');
  a.doSomething();
});
涉及面试题:
  • AMD 和 CMD 的特性

4. Proxy

ES6 引入的Proxy对象用于创建一个对象的代理,从而实现对对象的拦截和自定义行为。Proxy 可以用于实现许多高级特性,如数据响应式。以下是一个简单的例子:

let handler = {
  get: function(target, property, receiver) {
    console.log(`Getting ${property}`);
    return Reflect.get(target, property, receiver);
  },
  set: function(target, property, value, receiver) {
    console.log(`Setting ${property} = ${value}`);
    return Reflect.set(target, property, value, receiver);
  }
};

let obj = new Proxy({}, handler);
obj.name = "John"; // Setting name = John
console.log(obj.name); // Getting name

Proxy 可以捕获对象的各种操作,如读取属性、设置属性等,为开发者提供了更多的控制力。

涉及面试题:
  • Proxy 可以实现什么功能?

5. map, filter, reduce

这三个数组方法是在ES5中引入的,但在ES6中得到了进一步的强化和普及。

5.1 map

map 方法创建一个新数组,其结果是对原数组中的每个元素调用提供的函数进行处理。

let array = [1, 2, 3];
let mappedArray = array.map(value => value * 2);
console.log(mappedArray); // [2, 4, 6]
5.2 filter

filter 方法创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。

let array = [1, 2, 4, 6];
let newArray = array.filter(item => item !== 6);
console.log(newArray); // [1, 2, 4]
5.3 reduce

reduce 方法用于将数组中的元素通过提供的函数逐个累积为单个值。

const arr = [1, 2, 3];
const sum = arr.reduce((acc, current) => acc + current, 0);
console.log(sum); // 6
涉及面试题:
  • map、filter、reduce 各自有什么作用?

6. Map、WeakMap、Object 区别

这三者都是用于存储键值对的容器,但在使用场景和特性上存在一些差异。

6.1 Object

Object 的键只能为字符串或者符号。
Object 是无序的,属性的顺序不受保证。
Object 的键值对是显式的,可以通过Object.keys()获取所有键。

6.2 Map

Map 的键可以是任意类型。
Map 是有序的,键值对的顺序与插入顺序一致。
Map 是可迭代的,可以直接进行遍历。

let map = new Map();
map.set("a", 1);
map.set("b", 2);
for (let [key, value] of map) {
  console.log(key, value);
}
6.3 WeakMap

WeakMap 的键只能是对象。
WeakMap 是弱引用,不会阻止被引用对象被垃圾回收。
WeakMap 没有迭代方法,不能直接遍历。

let weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, "some value");
涉及面试题:
  • Map、WeakMap、Object 的区别是什么?

原文链接

面试宝典之ES6知识点

你可能感兴趣的:(面试,es6,职场和发展)