前端面试准备-------ES6

10 篇文章 0 订阅
8 篇文章 0 订阅
本文详细介绍了前端面试中常见的ES6知识点,包括let、const的声明,解构赋值,类与继承,Promise的使用,generator异步编程,箭头函数的this指向,Map和Set的应用,数组去重,以及ES6转译为ES5的原理。通过阅读,读者可以深入理解ES6的关键特性并应用于实际项目。
摘要由CSDN通过智能技术生成

本文是根据知乎 爱前端不爱恋爱提供的目录整理供大家学习,后将持续更新
1、声明 let、const
2、解构赋值
3、声明类与继承:class、extend
4、Promise的使用与实现
5、generator(异步编程、yield、next()、await 、async)
6、箭头函数this指向问题、拓展运算符
7、map和set有没有用过,如何实现一个数组去重,map数据结构有什么优点?
8、ES6怎么编译成ES5,css-loader原理,过程
9、使用es5实现es6的class

一、声明 let、const

let 声明的变量只在 let 命令所在的代码块内有效。

const 声明一个只读的常量,一旦声明,常量的值就不能改变。

var i =10;
for(var i = 0;i<5;i++){
	console.log(i);
}
console.log(i);
var i =10;
for(let i = 0;i<5;i++){
	console.log(i);
}
console.log(i);

在这里插入图片描述
可见let定义的变量只在for循环这一块级作用域内起作用。
let 只能声明一次 var 可以声明多次

const R = 3; 
R = 4;

const
const声明一个只读变量,声明之后不允许改变。意味着,一旦声明必须初始化,否则会报错。
letconst不存在变量提升,var 会变量提升:(变量提升是编译器自动将声明变量放到代码开始,也就是可以先使用再声明

console.log(i);
let  i =1;//报错
const  i =1;//报错
var i =1;//1

ES6 明确规定,代码块内如果存在 let 或者 const,代码块会对这些命令声明的变量从块的开始就形成一个封闭作用域。

二、解构赋值

解构赋值是对赋值运算符的扩展。

他是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。

在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。

  1. 数组模型的解构(Array)
let [a, [[b], c]] = [1, [[2], 3]];
// a = 1
// b = 2
// c = 3
let [a, b, c, d, e] = 'hello';
// a = 'h'
// b = 'e'
// c = 'l'
// d = 'l'
// e = 'o'
  1. 对象模型的解构(Object)
let obj = {p: ['hello', {y: 'world'}] };
let {p: [x, { y }] } = obj;
// x = 'hello'
// y = 'world'
let obj = {p: ['hello', {y: 'world'}] };
let {p: [x, {  }] } = obj;
// x = 'hello'

三、声明类与继承:class、extend

class(类)作为对象的模板被引入,可以通过 class 关键字定义类。class 的本质是 function。它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法。

// 匿名类
let Example = class {
    constructor(a) {
        this.a = a;
    }
}
// 命名类
let Example = class Example {
    constructor(a) {
        this.a = a;
    }
}

类定义不会被提升,这意味着,必须在访问前对类进行定义,否则就会报错。不可重复声明。类中方法不需要 function 关键字。方法间不能加分号。

class Example{
    constructor(){
      console.log('我是constructor');
    }
}
new Example(); // 我是constructor

constructor 方法是类的默认方法,创建类的实例化对象时被调用。
class 的实例化必须通过 new 关键字。
extends
通过 extends 实现类的继承。

class Child extends Father { ... }

子类 constructor 方法中必须有 super ,且必须出现在 this 之前。

四、Promise的使用与实现

Promise是异步编程的一种解决方案。

从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。

特点
Promise 异步操作有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。除了异步操作的结果,任何其他操作都无法改变这个状态。

Promise 对象只有:从 pending 变为 fulfilled 和从 pending 变为 rejected 的状态改变。只要处于 fulfilledrejected ,状态就不会再变了即 resolved(已定型)。

const p1 = new Promise(function(resolve,reject){
    resolve('success1');
    resolve('success2');
}); 
const p2 = new Promise(function(resolve,reject){  
    resolve('success3'); 
    reject('reject');
});
p1.then(function(value){  
    console.log(value); // success1
});
p2.then(function(value){ 
    console.log(value); // success3
});

缺点:
无法取消 Promise ,一旦新建它就会立即执行,无法中途取消。

如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。

当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

五、generator(异步编程、yield、next()、await 、async)

Generator 函数,可以通过 yield 关键字,把函数的执行流挂起,为改变执行流程提供了可能,从而为异步编程提供解决方案。

Generator 有两个区分于普通函数的部分:

  • 一是在 function 后面,函数名之前有个 *
  • 函数内部有 yield 表达式。

其中 * 用来表示函数为 Generator 函数,yield 用来定义函数内部的状态。

function* sendParameter(){
    console.log("strat");
    var x = yield '2';
    console.log("one:" + x);
    var y = yield '3';
    console.log("two:" + y);
    console.log("total:" + (x + y));
}

var sendp1 = sendParameter();
sendp1.next();
// strat
// {value: "2", done: false}
sendp1.next();
// one:undefined
// {value: "3", done: false}
sendp1.next();
// two:undefined
// total:NaN
// {value: undefined, done: true}
var sendp2 = sendParameter();
sendp2.next(10);
// strat
// {value: "2", done: false}
sendp2.next(20);
// one:20
// {value: "3", done: false}
sendp2.next(30);
// two:30
// total:50
// {value: undefined, done: true}
}

一般情况下,next 方法不传入参数的时候,yield 表达式的返回值是 undefined 。当 next 传入参数的时候,该参数会作为上一步yield的返回值。

yield* 表达式表示 yield 返回一个遍历器对象,用于在 Generator 函数内部,调用另一个 Generator 函数。

async
asyncES7 才有的与异步操作有关的关键字,和 PromiseGenerator 有很大关联的。

async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。

async function helloAsync(){
    return "helloAsync";
  }
  
console.log(helloAsync())  // Promise {<resolved>: "helloAsync"}
 
helloAsync().then(v=>{
   console.log(v);         // helloAsync
})

await
await 操作符用于等待一个 Promise 对象, 它只能在异步函数 async function 内部使用。
返回 Promise 对象的处理结果。如果等待的不是 Promise 对象,则返回该值本身。

如果一个 Promise 被传递给一个 await 操作符,await 将等待 Promise 正常处理完成并返回其处理结果。

function testAwait (x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}
 
async function helloAsync() {
  var x = await testAwait ("hello world");
  console.log(x); 
}
helloAsync ();
// hello world

正常情况下,await 命令后面是一个 Promise 对象,它也可以跟其他值,如字符串,布尔值,数值以及普通函数。
await针对所跟不同表达式的处理方式:

  • Promise 对象:await 会暂停执行,等待 Promise 对象 resolve,然后恢复 async 函数的执行并返回解析值。
  • Promise 对象:直接返回对应的值。

六、箭头函数this指向问题、拓展运算符

箭头函数提供了一种更加简洁的函数书写方式。不可以作为构造函数,也就是不能使用 new 命令,否则会报错

var f = v => v;
//等价于
var f = function(a){
 return a;
}
f(1);  //1

箭头函数没有参数或者有多个参数,要用 () 括起来。

箭头函数函数体有多行语句,用 {} 包裹起来,表示代码块,当只有一行语句,并且需要返回结果时,可以省略 {} , 结果会自动返回。

箭头函数要返回对象的时候,为了区分于代码块,要用 () 将对象包裹起来

// 报错
var f = (id,name) => {id: id, name: name};
f(6,2);  // SyntaxError: Unexpected token :
 
// 不报错
var f = (id,name) => ({id: id, name: name});
f(6,2);  // {id: 6, name: 2}

this

var func = () => {
  // 箭头函数里面没有 this 对象,
  // 此时的 this 是外层的 this 对象,即 Window 
  console.log(this)
}
func(55)  // Window 
 
var func = () => {    
  console.log(arguments)
}
func(55);  // ReferenceError: arguments is not defined

箭头函数体中的 this 对象,是定义函数时的对象,而不是使用函数时的对象。

function fn(){
  setTimeout(()=>{
    // 定义时,this 绑定的是 fn 中的 this 对象
    console.log(this.a);
  },0)
}
var a = 20;
// fn 的 this 对象为 {a: 19}
fn.call({a: 18});  // 18
// 回调函数
var Person = {
    'age': 18,
    'sayHello': function () {
      setTimeout(function () {
        console.log(this.age);
      });
    }
};
var age = 20;
Person.sayHello();  // 20
 
var Person1 = {
    'age': 18,
    'sayHello': function () {
      setTimeout(()=>{
        console.log(this.age);
      });
    }
};
var age = 20;
Person1.sayHello();  // 18

拓展运算符

拓展运算符 ...复制后面对象的参数给当前变量

var arr1 = [1,2];
var arr2 = [...arr1];
console.log(arr2);//[1,2]

es6之扩展运算符 三个点(…)

七、map和set有没有用过,如何实现一个数组去重,map数据结构有什么优点?

Map 对象
Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
MapsObjects 的区别

  • 一个 Object 的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值。
  • Map 中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。
  • Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
  • Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。

for…of

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
 
// 将会显示两个 log。 一个是 "0 = zero" 另一个是 "1 = one"
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
for (var [key, value] of myMap.entries()) {
  console.log(key + " = " + value);
}
/* 这个 entries 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的 [key, value] 数组。 */
 
// 将会显示两个log。 一个是 "0" 另一个是 "1"
for (var key of myMap.keys()) {
  console.log(key);
}
/* 这个 keys 方法返回一个新的 Iterator 对象, 它按插入顺序包含了 Map 对象中每个元素的键。 */
 
// 将会显示两个log。 一个是 "zero" 另一个是 "one"
for (var value of myMap.values()) {
  console.log(value);
}
/* 这个 values 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的值。 */

forEach()

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
 
// 将会显示两个 logs。 一个是 "0 = zero" 另一个是 "1 = one"
myMap.forEach(function(value, key) {
  console.log(key + " = " + value);
}, myMap)

Map 与 Array的转换

var kvArray = [["key1", "value1"], ["key2", "value2"]];
 
// Map 构造函数可以将一个 二维 键值对数组转换成一个 Map 对象
var myMap = new Map(kvArray);
 
// 使用 Array.from 函数可以将一个 Map 对象转换成一个二维键值对数组
var outArray = Array.from(myMap);

Set 对象
Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。

Set 中的特殊值
Set 对象存储的值总是唯一的,所以需要判断两个值是否恒等。有几个特殊值需要特殊对待:

  • +0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复;
  • undefinedundefined 是恒等的,所以不重复;
  • NaNNaN 是不恒等的,但是在 Set 中只能存一个,不重复。
let mySet = new Set();
 
mySet.add(1); // Set(1) {1}
mySet.add(5); // Set(2) {1, 5}
mySet.add(5); // Set(2) {1, 5} 这里体现了值的唯一性
mySet.add("some text"); 
// Set(3) {1, 5, "some text"} 这里体现了类型的多样性
var o = {a: 1, b: 2}; 
mySet.add(o);
mySet.add({a: 1, b: 2}); 
// Set(5) {1, 5, "some text", {…}, {…}} 
// 这里体现了对象之间引用不同不恒等,即使值相同,Set 也能存储

类型转换
// Array 转 Set
var mySet = new Set([“value1”, “value2”, “value3”]);
// 用…操作符,将 Set 转 Array
var myArray = […mySet];
String
// String 转 Set
var mySet = new Set(‘hello’); // Set(4) {“h”, “e”, “l”, “o”}
// 注:Set 中 toString 方法是不能将 Set 转换成 String

数组去重

var mySet = new Set([1, 2, 3, 4, 4]);
[...mySet]; // [1, 2, 3, 4]

八、ES6怎么编译成ES5,css-loader原理,过程

Babel 是一个 JavaScript 编译器
Babel 是一个工具链,主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
css-loader原理,过程
loader 用于对模块的源代码进行转换。loader 可以使你在 import 或"加载"模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。
css-loader是分析各个css文件的关系并合并成一个css
Babel使用指南
关于es6及以上的js编译成es5

九、使用es5实现es6的class

ES6中的class在ES5中的实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值