第三篇
一些常见的面试题内容,希望也能助你一臂之力🌸🌸🌸🌸🌸
Q1、ES6新增的set集合是什么?
ES6提供新的数据结构,类似于数组,但成员的值都是唯一的
集合实现了iterator接口,可以使用扩展运算符和for .. of进行遍历
// 常使用API
// 声明一个set集合
let s = new Set();
// 自动去重
let s1 = new Set(['大事情','小事情','大事情','坏事情','好事情'])
// 元素个数
console.log(s1.size); //4
// 添加新的元素
s1.add('开心')
// 删除元素
s1.delete('坏事情')
// 检测
console.log(s1.has("开心")) // true
// 使用for of遍历
for(let v of s1){
console.log(v) //大事情 小事情 好事情 开心
}
//清空
s1.clear();
console.log(s1); // Set(0) {size: 0}
// 举个例子
// 声明两个数组
let arr1 = [1,3,2,3,4,7,8,4,2,3,9];
let arr2 = [2,3,7,5,7,5,4,1];
// 1、数组去重
let result1 = [...new Set(arr1)]; //使用扩展运算符
console.log(result1); //(7) [1, 3, 2, 4, 7, 8, 9]
// 2、求交集
// 扩展运算符将每一项展开 过滤写法
// let result2 = [...new Set(arr1)].filter(item=>{
// let s2 = new Set(arr2);
// if(s2.has(item)){
// return true;
// }else{
// return false;
// }
// })
//简写
let result2 = [...new Set(arr1)].filter(item => new Set(arr2).has(item))
console.log(result2); //(5) [1, 3, 2, 4, 7]
//3、求并集
let union = [...arr1,...arr2];
let result3 = new Set(union)
console.log(result3); //Set(8) {1, 3, 2, 4, 7, …}
// 4、求差集
let result4 = [...new Set(arr1)].filter(item=>!(new Set(arr2).has(item)))
console.log(result4); //(2) [8, 9]
Q2、什么是map?
ES6提供的新数据结构,类似于对象,也是键值对的集合。”键值“不限于字符串,也可以是各类型的值(对象)。
map实现了iterator接口,可以使用扩展运算符 和 for...of 进行遍历
相关属性和方法:
size、set、get 、has、 clear
// 举个例子
// 声明map
let m = new Map();
// 添加元素
m.set('name','小天');
m.set('change',function(){
console.log("学习前端开发!")
})
let key = {
school:'ATGUIGU'
}
m.set(key,['北京','上海','天津'])
// 获取长度
console.log(m.size) //3
// 获取属性值
console.log(m.get('change')) // f(){ console.log("学习前端开发!") }
// 是否存在某个属性
console.log(m.has('name')) //true
// 删除
m.delete('name')
// 清除
m.clear();
Q3、Class 的基本语法
实例化对象
// ES5实例化一个对象
function Phone(brand,price){
this.brand = brand,
this.price = price
}
// 添加方法
Phone.prototype.call = function(){
console.log("打电话的手机!")
}
// 实例化对象
let HuaWei = new Phone('华为I8',8555);
console.log(HuaWei); // Phone {brand: '华为I8', price: 8555}
// ES6 使用class 实例化对象
class Shouji{
// 构造方法,名字不能修改
constructor(brand,price){
this.brand = brand,
this.price = price
}
// 添加方法
call(){
console.log("发短信的手机!")
}
}
let onePlus = new Shouji("1+",1200);
console.log(onePlus); // Shouji {brand: '1+', price: 1200}
// ES6的类
1、类的数据类型就是函数,类本身就指向构造函数。
使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致
class Point{
say(){
console.log('hello class');
}
}
console.log(typeof Point) // function
console.log(Point === Point.prototype.constructor) //true
// 使用new 关键字实例化一个类
const p = new Point();
p.say(); // hello class
// 表达式的形式定义类
// 这个类的名字是Me,但是Me只在 Class 的内部可用,指代当前类。
// 在 Class 外部,这个类只能用MyClass引用
const MyClass = class Me {
getClassName() {
return Me.name; //内部使用
}
};
let my = new MyClass();
my.getClassName() // Me
// Me.name // ReferenceError: Me is not defined
静态成员
// 静态属性属于类(构造函数对象身上的属性可以获取得到),但是实例自身上不能获取得到
class Phone{
// 静态属性
static name = '手机';
// 静态方法
static change(){
console.log("摔不坏")
}
}
let nokia = new Phone();
console.log(nokia.name); //实例 undefined
console.log(Phone.name); //函数对象身上 手机
Q4、Class 的继承
ES5的继承:让子级原型,成为父级的实例上的一个实例对象
// ES5实现继承
function Phone(brand,price){
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function(){
console.log("我是父级身上的方法")
}
function Shouji(brand,price,color,size){
Phone.call(this,brand,price);
this.color = color;
this.size = size
}
//设置子级原型,成为父级的实例上的一个实例对象
Shouji.prototype = new Phone;
// 修改子级上的构造函数指向
Shouji.prototype.constructor = Shouji;
// 声明子类的方法
Shouji.prototype.play = function(){
console.log("我是子级身上的方法")
}
let parrent = new Phone("华为",8000); //父类的实例
let children = new Shouji('I8系列',2000,'black','4.5inch'); //子类实例
children.play(); //子类调用自身上的方法
children.call(); // 子类调用父级身上的方法
// ES6实现继承
class Phone{
constructor(brand,price){
this.brand = brand;
this.price = price
}
// 方法
call(){
console.log("打电话!")
}
}
// 子类
class SmartPhone extends Phone{
// 构造方法
constructor(brand,price,color,size){
super(brand,price); //Phone.call(this,brand,price);
this.color = color;
this.price = price
}
photo(){
console.log('我是子类自生上是方法')
}
// 我是子类对父类方法的重写 ES5不可以
call(){
console.log('我是子类对父类方法的重写')
}
}
const xiaomi = new SmartPhone('小米',799,'white','4.7inch')
xiaomi.photo(); // 子类自生上的方法
xiaomi.call(); // 子类对父类方法的继承
Q5、ES6新增加的数值扩展有哪些?
// (1)Number.isFinite //检测一个数值是否为有限数
console.log(Number.isFinite(15)) //true
console.log(Number.isFinite(0.8)) //true
console.log(Number.isFinite(Infinity)) //false
console.log(Number.isFinite('15')) //false
console.log(Number.isFinite(true)) //false
// (2) Number.isNaN //判断是否为NAN
console.log(Number.isNaN(NaN)) //true
console.log(Number.isNaN(15)) //false
// (3)Number.parseInt // (4)Number.parseFloat
// 将全局方法parseInt()和parseFloat(),移植到Number对象上面
//ES5写法
console.log(parseInt('3.14259')) //3
console.log(parseFloat('3.14Π')) // 3.14
//ES6写法
console.log(Number.parseInt('3.14159')) //3
console.log(Number.parseFloat('3.14Π')) // 3.14
// (5)Number.isInteger //是否为整数
console.log(Number.isInteger(25) ) // true
console.log( Number.isInteger(25.1)) // false
// (6)Math.tunrc //用于去除一个数的小数部分,返回整数部分
console.log(Math.trunc(4.1)) //4
console.log(Math.trunc(4.9)) //4
console.log(Math.trunc(-4.1)) //-4
console.log(Math.trunc(-4.9)) //-4
Q6、ES6模块化是什么?
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
CommonJS(输入时必须查找对象属性) 和 AMD 模块,都只能在运行时确定这些东西。
模块化优点是:防止命名冲突、代码复用、高维护性
// CommonJS模块
let { stat, exists, readfile } = require('fs');
// ES6模块
import { stat, exists, readFile } from 'fs';
模块功能主要由两个命令构成:export和import。
export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。
外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。
对外暴露方式:
//分别暴露
export let school = {
name:'大前端'
}
export function fun(){
console.log('学习ES6')
}
//统一暴露
let school = 'W3C'
function fun(){
console.log('第二种暴露方式')
}
export {school,fun};
//默认暴露
export default{
school:'W3CSchool',
change:function(){
console.log('第三种暴露方式')
}
}
// 使用默认暴露中的方法
m1.default.change();
模块引入方式:
//模块化引入(第一种)
// 通用的导入方式
// 引入m1.js
// import * as m1 from './m1.js';
// 解构赋值的形式
// 对分别暴露
// import {school,fun} from './m1.js';
// 对统一暴露 同名的可以重名
//import {school as scl,fun} from './m1.js'
//对默认暴露方式
// import {default as m1 } from './m1.js'
// 简便形式 默认暴露
// import m1 from './m1.js'
// 模块化引入(第二种)
// 入口文件
// 模块引入
import * as m1 from './m1.js';
// src 引入
<script src="./app.js" type="module"></script>
Q7、为什么引入 async 函数以及其作用?
async 函数 使得异步操作变得更加方便,它就是 Generator 函数的语法糖(使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会)
// 举个例子
//Generator 函数,依次读取两个文件
const fs = require('fs');
const readFile = function (fileName) {
return new Promise(function (resolve, reject) {
fs.readFile(fileName, function(error, data) {
if (error) return reject(error);
resolve(data);
});
});
};
const gen = function* () {
const f1 = yield readFile('/etc/fstab');
const f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
// async 函数,依次读取两个文件
const asyncReadFile = async function () {
const f1 = await readFile('/etc/fstab');
const f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
Q8、async函数的改进体现在哪些方面?【By:ES6阮一峰】
(1)内置执行器:asyncReadFile(); 调用该函数,代码自动执行,输出最后结果
Generator 函数,需要调用next方法,或者用co模块,才能继续往下执行。
(2)语义更加明了
async和await,比起 * 和 yield,语义更清楚了。
async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果
(3)使用范围广
co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象。
而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)
(4)返回值是 Promise。
async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。
可以用then方法指定下一步的操作
async函数的基本使用
async函数返回一个 Promise 对象,可以使用then方法添加回调函数。
当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句
// 函数声明
async function foo() {}
// 函数表达式
const foo = async function () {};
// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)
// Class 的方法
class Storage {
constructor() {
this.cachePromise = caches.open('avatars');
}
async getAvatar(name) {
const cache = await this.cachePromise;
return cache.match(`/avatars/${name}.jpg`);
}
}
const storage = new Storage();
storage.getAvatar('jake').then(…);
// 箭头函数
const foo = async () => {};
Q9、await命令
1、await必须写在async函数中
2、await右侧的表达式一般为promise对象,如果不是 Promise 对象,就直接返回对应的值。
3、await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。
如果希望await后 Promise 对象变为reject,但不中断后面的异步操作。
可以将第一个await放在try...catch结构里面,这样不管这个异步操作是否成功,第二个await都会执行。
// 举个例子
// 第一种
async function mian(){
try {
await Promise.reject('出错了!')
} catch (error) {
return await Promise.resolve('不影响后续执行')
}
}
mian().then(
v => console.log(v)
)
// 结果: 不影响后续执行
// await后面的 Promise 对象再跟一个catch方法,处理前面可能出现的错误。
// 第二种
async function Main(){
await Promise.reject('出错了!').catch(
e => console.log(e) //处理肯出现的错误
)
return await Promise.resolve('不影响后续执行')
}
Main().then(
v => console.log(v)
)
// 结果:出错了!
// 不影响后续执行
Q10、async函数的执行原理?
将 Generator 函数和自动执行器,包装在一个函数里。
// 举个例子
async function fun(args) {
// ...
}
// 等同于
function fun(args) {
return spawn(function* () { // spawn函数就是自动执行器
// ...
});
}
休息一下,下一篇下一篇