ES6+(前端面试题整合)

谈一谈let与var和const的区别

let为ES6新添加申明变量的命令,它类似于var,但是有以下不同:

  • let命令不存在变量提升,如果在let前使用,会导致报错
  • let暂时性死区的本质,其实还是块级作用域必须“先声明后使用”的性质,let 暂时性死区的原因:var 会变量提升,let 不会。
  • let,const和class声明的全局变量不是全局对象的属性
  • const可以在多个模块间共享
  • const声明的变量与let声明的变量类似,它们的不同之处在于,const声明的变量只可以在声明时赋值,不可随意修改,否则会导致SyntaxError(语法错误)
  • const只是保证变量名指向的地址不变,并不保证该地址的数据不变

说说箭头函数的特点

  • 箭头函数不属于普通的 function,所以没有独立的上下文。
  • 箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
  • 由于箭头函数没有自己的this,函数对象中的call、apply、bind三个方法,无法"覆盖"箭头函数中的this值。
  • 箭头函数没有原本(传统)的函数有的隐藏arguments对象。
  • 箭头函数不能当作generators使用,使用yield会产生错误。

在以下场景中不要使用箭头函数去定义:

1. 定义对象方法、定义原型方法、定义构造函数、定义事件回调函数。

2. 箭头函数里不但没有 this,也没有 arguments, super

对Symbol,Map和Set的理解

Symbol 是一种特殊的、不可变的数据类型,可以作为对象属性的标识符使用,即使使用同样的参数实例化symbol,得到的symbol实例也不会相等

1let _symbol1 = Symbol('test'); 2let _symbol2 = Symbol('test'); 3console.log(_symbol1 == _symbol2);//false

Map对象保存键值对,有点类似于Object,但是Object的键只能是字符串或者Symbols,而Map可以是任何值

1 let myMap = new Map() 2 let str1 = 'dog' 3 let str2 = 'cat' 4 myMap.set(str1, '汪') 5 myMap.set(str2, '喵') 6 console.log(myMap) // {0: {"dog" => "汪"}1: {"cat" => "喵"}} 7 console.log(myMap.get(str1)) // 汪

Set 对象允许你存储任何类型的唯一值(数组去重),有点类似于Array,Set中的元素只会出现一次

1 let mySet = new Set() 2 mySet.add('hello') 3 mySet.add('1') 4 mySet.add('2') 5 mySet.add('2') 6 console.log(mySet) // {0: "hello",1: "1",2: "2"}

使用ES6如何监测数组变化(proxy监测读写)

1 let list = [1, 2, 3] 2 // 代理 3 let _proxy = new Proxy(list, { 4 set: function (target, prop, val, rec) { 5 console.log('写入') 6 target[prop] = val 7 return true 8 }, 9 get: function (target, prop) { 10 console.log('读取') 11 return target[prop] 12 } 13 }) 14 _proxy[0] = 4 // 写入 15 console.log(_proxy[1]) // 读取

JS有哪些处理异步的方法

回调函数:回调是一个函数被作为一个参数传递到另一个函数里,在那个函数执行完后再执行

**优点:简单,方便,实用,易懂
缺点:当逻辑复杂时,会产生回调函数地狱,耦合度高,流程会很混乱
**

1 // 回调 2 let cb = (props) => { 3 console.log(props) // 2 4 } 5 let init = (props) => { 6 // 异步操作 7 setTimeout(() => { 8 cb(props) // 异步传参 9 }, 1000) 10 } 11 init(2) 12 console.log(1) // 1

事件发布/订阅:采用事件驱动模式,任务的执行取决于某一个事件是否发生

**优点:事件监听方式相对回调实现了代码的解耦,对模块化开发很友好
缺点:每次执行任务都需要发布/订阅事件
**

1 // 事件发布/订阅 2 let cb = (event) => { 3 console.log(event.props) // 2 4 } 5 let init = (props) => { 6 // 异步操作 7 setTimeout(() => { 8 let event = new Event('myEvent') 9 event.props = props // 异步传参 10 document.dispatchEvent(event) 11 }, 1000) 12 } 13 init(2) 14 console.log(1) // 1 15 document.addEventListener('myEvent', cb)

Promise:Promise是异步编程,它将异步操作以同步的方式表现出来,避免回调地狱的产生

**优点:避免回调地狱,链式调用,函数思路清晰,逻辑相对前两者更强
缺点:理解性差,异步操作在promise构造函数内部
**

1 // ES6 Promise 2 let init = (props) => { 3 return new Promise((resolve, reject) => { 4 // 异步操作 5 setTimeout(() => { 6 resolve(props) 7 }, 1000) 8 }) 9 } 10 init(2).then((res) => { 11 console.log(res) // 2 12 }) 13 console.log(1) // 1

Generator:generator(生成器)是ES6标准引入Python的新的数据类型

**优点:取消链式调用的then,和发布/订阅模式非常相似,对于理解同步操作很直观
缺点:多个异步函数时不够直观,原函数需要通过next去维护外部函数的yield
**

1 // ES6 Generator 2 const fn = init(2) 3 let cb = (props) => { 4 console.log(props) // 2 5 } 6 function* init(props) { 7 // 异步操作 8 yield setTimeout(() => { 9 fn.next() 10 }, 500) 11 yield setTimeout(() => { 12 fn.next() 13 }, 500) 14 cb(props) 15 } 16 fn.next() 17 console.log(1) // 1

async/await:async函数是generator函数的语法糖,函数(function关键字)前添加async关键字,函数中通过await等待异步执行

**优点:同步流程清晰,简洁,异步操作可以返回promise对象,后续操作更方便
缺点:JS的执行器功能较其他co模块较弱
**

1 // ES6+ async/await 2 let cb = (props) => { 3 console.log(props) // 2 4 } 5 let cb2 = (props) => { 6 return new Promise((resolve, reject) => { 7 setTimeout(() => { 8 resolve(props) 9 }, 1000) 10 }) 11 } 12 async function init(props) { 13 // 异步操作 14 let num2 = await cb2(props) 15 cb(num2) 16 } 17 init(2) 18 console.log(1) // 1

ES6中的class关键字跟function什么区别

  • 在function定义的构造函数中,其prototype.constructor属性指向构造器自身,在class定义的类中,constructor其实也相当于定义在prototype属性上
  • function如果重复定义,会覆盖之前定义的方法,而class重复定义则会报错
  • class中定义的方法不可用Object.keys(Point.prototype)枚举到,function构造器原型方法可被Object.keys(Point.prototype)枚举到
  • class没有变量提升,也就是说,必须先定义class,再使用,而function定义后,会被提升至当前作用域顶端
  • class定义的类没有私有方法和私有属性,function可以通过闭包实现私有方法和属性

ES6新增哪些数组方法

**find():返回数组中第一个满足条件的元素(如果有的话), 如果没有,则返回 undefined
findIndex():返回数组中第一个满足条件的元素的索引(如果有的话), 如果没有,则返回 -1
keys():返回一个数组索引的迭代器
values():返回一个数组迭代器对象,该对象包含数组中每个索引的值
entries():返回一个数组迭代器对象,该对象包含数组中每个索引的键值对

**

for in 和 for of 的****区别

for in 适合用于遍历对象,for of可以用来遍历数组,类数组对象,argument,字符串,Map和Set

for in 遍历数组时会有以下问题:

  • index索引为字符串型数字,不能直接进行几何运算
  • 遍历顺序有可能不是按照实际数组的内部顺序
  • 使用for in会遍历数组所有的可枚举属性,包括原型,原型上的方法和属性

所以for in 不适合遍历数组,而适合用于遍历对象

而for of遍历数组时

只会遍历数组内的元素,而不包括数组的原型属性method和索引name

CommonJS 中的 require/exports 和 ES6 中的 import/export 区别

  • CommonJS模块输出的是一个值的拷贝,ES6模块输出的是值的引用
  • CommonJS模块是运行时加载,ES6模块是编译时输出接口,ES6可以在编译时就完成模块加载,效率要比CommonJS模块的加载方式高
  • CommonJS模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。而Es6模块的运行机制与CommonJS不一样。JS引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,在根据引用到被加载的那个模块里面去取值。ES6模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
  • require/exports是CommonJS在Node中实现的,import/export是ES6的模块
  • require/exports是同步导入,因为用于服务端,文件都在本地,同步导入即使卡住主线程影响也不大。而ES6模块是异步导入,因为用于浏览器,需要下载文件,如果也采用导入会对渲染有很大影响
  • ES6模块的设计思想,是尽量静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量,ES6模块会编译成 require/exports 来执行的
  • export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能

尝试实现Promise

https://blog.csdn.net/time_____/article/details/109721703

Object.is()与“==”,“===”的区别

“==”会在比较时进行类型转换

“===”比较时不进行隐式类型转换

Object.is()在三等号判等的基础上特别处理了NaN、-0和+0,保证-0和+0不再相同,但Object.is(NaN,NaN)会返回true

ES6中为何出现Class

Class的功能实际上在ES5都能实现,可以算是ES6的语法糖,其作用是使JS语法清晰,更像面向对象语法

基础写法

1 class MyEvent extends EventTarget { // 继承EventTarget 2 constructor(e) { 3 super(e) // 父类的构造函数 4 this.consoleThis() // 执行函数 5 } 6 consoleThis() { 7 console.log(this) 8 } 9 } 10 let myEvent = new MyEvent(document) // EventTarget 

ES6语法糖的对象的属性简写和属性名表达式是什么

属性简写:对象的字面量可以直接写入与之名称相同的变量和函数

1 let name = '小明' 2 function showName() { 3 console.log(this.name) 4 } 5 let person = { 6 name, 7 showName 8 } 9 console.log(person.name)// 小明 10 person.showName()// 小明

属性名表达式简写:ES6允许把表达式放在方括号内,作为对象的属性名

1 let num = 0 2 let obj = { 3 "1": 'a', 4 "2": 'b', 5 "3": 'c' 6 } 7 console.log(obj[++num]) // a 8 console.log(obj[++num]) // b 9 console.log(obj[++num]) // c

谈谈解构赋值的理解

解构赋值是对赋值运算符的扩展,是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值

1 // 数组 2 let [a, b, c] = [1, 2, 3]; 3 console.log(a, b, c) // 1,2,3 4 // 对象 5 let { 6 d, 7 e, 8 f 9 } = { 10 d: 4, 11 e: 5 12 }; 13 console.log(d, e, f) // 4,5,undefined

使用ES6如何合并多个对象,复制对象

ES6中的对象新增(...)拓展运算符,用于取出参数对象所有可遍历属性然后拷贝到当前对象

ES6新增对象拷贝方法:Object.assign(target, source1,source2,source3, ···),将源对象的所有可枚举属性复制到目标对象中,即,将source1,source2,source3......复制到target中

合并:

1 let name = { 2 name: '小明' 3 } 4 let age = { 5 age: 20 6 } 7 let hobby = { 8 hobby: 'music' 9 } 10 let person = {// 拓展运算符 11 ...name, 12 ...age, 13 ...hobby 14 } 15 console.log(person)// age: 20,hobby: "music",name: "小明" 16 17 Object.assign(person, name, age, hobby)// 对象拷贝 18 console.log(person) // age: 20,hobby: "music",name: "小明"

复制:

1 let list = [1, 2, 3, 4, 5] 2 let list2 = [...list]// 拓展运算符 3 Object.assign(list2, list)// 对象拷贝 4 let index = 0 5 do { 6 list[index] += 10 7 } while (index++ < list.length - 1) 8 console.log(list, list2) // [11, 12, 13, 14, 15] [1, 2, 3, 4, 5]

如何控制类中属性的读写性

setter...getter...

1 class Animal { 2 constructor() { 3 this._dog = '小黑' 4 this._cat = '小黄' 5 } 6 set cat(val) { // 只写 7 this._cat = val 8 } 9 get dog() { // 只读 10 return this._dog 11 } 12 } 13 let animal = new Animal() 14 animal.dog = '小白' 15 animal.cat = '小灰' 16 console.log(animal.dog, animal.cat) // 小黑 undefined 17 console.log(animal._dog, animal._cat) // 小黑 小灰

Object.defineProperty()修改对象只读

1 class Animal { 2 constructor() { 3 this.dog = '小白' 4 } 5 } 6 let animal = new Animal() 7 Object.defineProperty(animal, 'dog', { 8 writable: false, // 可写,false为只读 9 }); 10 animal.dog = '小黑' 11 console.log(animal.dog) // 小白
点赞
收藏

评论区

加载中...

相关推荐

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

javascript实践教程-03-变量

本节目标1.掌握声明变量的方式。2.掌握var和let的区别。内容摘要本篇讲解了变量声明的两种方式var和let,并对比var和let声明变量的差别,最后对变量名名称规则进行了总结。阅读时间1015分钟变量基础js中声明变量可以使用var和let关键词。其中var是es5的语法,let是es6的语法。var声明变量var可以用来声明局部变量和全局变

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

ES6之常用开发知识点:入门(一)

ES6介绍ES6,全称ECMAScript6.0,2015.06发版。let和const命令let命令let命令,用来声明变量。它的用法类似于var,区别在于var声明的变量全局有效,let声明的变量只在它所在的代码块内有效。使用var声明:vara

ES6的let命令(二)

2.暂时性死区暂时性死区(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.51code.com%2F)是指只要块级作用域内存在let命令,它所声明的变量就绑定这个作用域,不会受到外部的影响。       varnum12;    if(true){    nu