Map和Set的区别,Map和Object的区别
Map和Set的区别:
- Map 和 Set 都不允许键重复
- 初始化需要的值不一样,Map需要的是一个二维数组,而Set 需要的是一维 Array 数组
- Set以[value, value]的形式储存元素,Map以[key,value]的形式储存元素
- map的值不作为键,键和值是分开的
- Map的键是不能修改,但是键对应的值是可以修改的;Set不能通过迭代器来改变Set的值,因为Set的值就是键。
- Map和Object的区别:
- Object的key 必须是简单数据类型(整数、字符串、symbol),map的key可以是任何类型
- Map的大小可以轻松通过size属性来获得,Object的大小必须通过自行获取
- Map是可迭代对象,可以轻松完成迭代;Object没有实现迭代协议,所以无法被for...of直接迭代(但可以自行实现迭代协议,或者使用Object.keys()或Object.entries()来迭代对象的键值和实体,for...in也可以迭代Object的可枚举属性);
- 频繁增减键值对时表现会更好
map、filter、every、some的区别
- map: 通过指定函数处理数组的每个元素,并返回处理后的数组,不会改变原数组;
- filter: 通过检查指定数组中符合条件的所有元素,并返回一个新数组,不会改变原数组;
- some: 用于检测数组的元素是否满足指定条件,有一个元素满足,则返回为true,剩余的元素不会再执行检测;没有满足条件的元素,则返回false;不会改变原数组,也不会检查空数组;
- every:用于检测数组中所有元素是否都符合指定条件;如果有一个不满足,则返回false,剩余的不会再进行检测;所有元素都满足,则返回true;
Promise.all、Promise.allSettled、Promise.race的区别
- 三者都是接收一个数组类型参数;
- Promise.all: 只有数组中全部promise都变为resolve的时候,返回一个新的Promise实例;当然,一旦有一个reject,状态就会变为rejected;
- Promise.allSettled:数组中的Promise不管是成功,还是失败,都会进入Promise.allSettled的.then的回调中,最后的返回值中,成功和失败都有一个status属性,成功的是fulfilled,失败的是rejected;成功含有value属性,失败则是reason属性;
- promise.race: 数组中的promise只要某一个成功或失败,就会返回成功或失败;
es6有哪些新特性
- 默认参数
- 模板对象:字符串拼接不再需要使用加号,还可以实现多行字符串;
- 解构赋值:
- 箭头函数
- Promise
- let、const(块级作用域)
- clase类
- modules(模块)
箭头函数和普通函数的区别
- 相比普通函数,箭头函数有更简洁的语法
- 箭头函数不绑定this,会捕获其所在的上下文的this值作为自己的this值;所以使用apply、call、bind对其没有任何影响;
- 箭头函数是匿名函数,不能作为构造函数,不可以使用new命令,否则会抛出一个错误;原因:构造函数的new都做了什么:
- JS内部会先生成一个新对象;
- 把新对象和构造函数通过原型链连接起来;
- 将构造函数的this指向新对象;
- 如果函数没有返回对象类型Object,那么new表达式中的函数调用会自动返回这个新对象;
- 箭头函数不绑定arguments,取而代之用rest参数...解决;所以箭头函数也没有arguments.callee和arguments.caller;
const testFunc = (...args)=>{
console.log(args) // 数组形式输出参数
}
-
let、var、const的区别?如果希望const定义的对象的属性也不能被修改该怎么做?
- let和var是声明变量的,const是声明常量的;
- let和const不存在变量的提升;
- let和const不允许重复的声明;
- let和const存在块级作用域;
- let和const存在暂时性死区:
let s = 1;
let Printing = function() {
console.log(s); // 报错 s is not defined
let s = 2;
}
const如果定义的是基本数据类型的话,是不可再修改的;如果定义的是引用数据类型(对象、数组),定义后是可以被修改的;const声明的对象,只是保存其对象的引用地址,只要地址不变,就不会报错;要使const定义的对象不可以变,可以:
使用Object.freeze(obj)冻结对象,就能使其内部的属性不可变;当然,要是对象的有属性是对象,就需要使用递归等方式一层层全部冻结;
栈和堆的区别:
- 栈是先进后出,堆是先进先出;
- 栈内存:存放基本数据类型;堆内存:存放引用数据类型(在栈内存中存一个基本类型值保存对象在堆内存中的地址,用于引用这个对象)
- 基本数据类型在当前执行环境结束时销毁,而引用类型不会随执行环境结束而销毁,只有当所有引用它的变量不存在时这个对象被垃圾回收机制回收;
- 栈内存存取速度较快,但是不灵活,同时由于结构简单,在变量使用完就可以将其释放,内存回收容易实现;
- 堆内存使用灵活,可以动态的增加或删除空间,但是存取比较慢;
闭包的原理、作用
- 什么是闭包:函数A中返回了函数B,函数B使用了函数A的作用域变量,此时函数B成为闭包;
- 原理:作用域链,因为作用域链就是在当前执行环境下访问了某个变量,如果不存在就一直往外层找,最终找到最外层也就是全局作用域,这就形成了一个链条;
- 作用:
- 不污染全局
- 变量私有化
- 形成块级作用域
- 函数自执行
instanceof的实现原理
- 作用:常用于判断一个实例是否属于某个类型
- 原理:查找构造函数的原型对象是否在实例对象的原型链上,如果是则返回true,否则返回false;
数据类型有哪些?如何判断一个数据是数组;
- 基本数据类型:Number、Bollean、String、Null、Undefined、Symbol、Biglnt
- 引用数据类型:Object
- Symbol:ES6新增,这种类型的对象永不相等,可以解决属性名冲突的问题
- Biglnt:谷歌67版本出现的,指安全存储,操作大整数;
- 判断一个数据是数组:
- Array.isArray(): es6新增
- 原型__proto__: [].proto === Array.prototype
- 构造器:[].constructor === Array
- Object.prototype.toString.call(): Object.prototype.toString.call([]) === "[object Array]"
- instanceof: [] instanceof Array
JQuery实现链式调用的原理是什么
- 链式调用是通过return this的形式来实现的,通过对象上的方法最后加上return this,把对象再返回回来,对象就可以继续调用方法,实现链式操作了;
- 链式调用的问题: 所有对象的方法返回的都是对象本身,也就是说没有返回值,所以这种方法不一定在任何环境下都适合;
原型、原型链、作用域、作用域链的含义和使用场景
- 原型:相当于一个模具,用来生产实例对象;
- 原型链: 原型对象有个指针指向构造函数,实例对象又有一个指针指向原型对象,这就形成了一条原型链,最终指向null;
- 作用域: 变量或者函数能作用的范围(全局作用域、局部作用域[函数内部用var声明的变量]、块级作用域)
- 作用域链: 变量随着函数一级一级往上搜索,直到找到为止,找不到就报错,这个过程就是作用域链起来的;
- 使用场景: 闭包、继承
前端工程化
- 定义:前端开发流程的标准化、工具化、规范化、简单化和自动化;目的就是为了提高开发过程中的开发效率,减少不必要的重复开发时间等;主要包括:项目工程化、代码模块化、页面组件化、编码规范化、构建自动化;
- 项目工程化:
- 工程化并非某种技术而是一种思想。
- 指使用软件工程的技术和方法来进行前端项目的开发、维护和管理。
- 比如在一个大型的web项目中,整个项目结构复杂而繁琐,需要多个团队配合才能很好地把控,那么我们就需要具备更高层次的思维去组织整个项目的技术选型、各种规范和项目构建等。
- 代码模块化:代码模块化可以理解为是一组自定义业务的抽象封装,是根据项目的内容来进行封装组合的;比如可以分为登录模块、购物车模块、订单模块等。模块可维护性好,组合灵活,方便调用,多人协作互不干扰;
- 页面组件化:指对具体的某个功能进行的封装,比如所有的表格可以封装为table来统一使用,以达到组件复用,提高开发效率;
- 编码规范:在项目规划初期制定的规范,对于后期的开发极为重要,大体的规范有:
- 命名规范
- 编码规范
- 结构规范
- 接口规范
- 文档规范
- 组件规范
- 代码版本管理规范(提交代码备注描述规范)
- UI规范(图标库等)
- 构建自动化:自动化也有很多自动化工具(webpack、glup...)代替我们完成一些机械重复的工作,例如:
- 持续集成
- 自动化构建
- 自动化部署
- 自动化测试