文章目录
一、js里面的数据类型有哪些
数据类型分为 简单数据类型和复杂数据类型 简单数据类型又分为 Number Boolean String undefined null symbol bigInt
Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。
bigInt 可以让js显示更大的数字 目前为止显示到2的63次方 263到263-1
复杂数据类型:对象(Object)、数组(Array)、函数(Function)
function和arrar也是数据类型 他是属于object类型的一种
二、new操作符做了那些事情?
1 创建了一个空对象
2 将这个空对象的 对象原型([[Prototype]]) 成员指向了构造函数的原型对象(prototype)
3 将构造函数对象的this设置为新创建的对象 执行
4 返回新对象
三、JS DOM 事件流
DOM 事件流 分为三个阶段 1 捕获阶段 2 当前阶段 3 冒泡阶段
1 捕获阶段 从外向内 找监听函数 叫事件捕获
2 当前目标阶段
3 冒泡阶段 从内向外 找监听函数 交事件冒泡
事件委托
事件委托就是利用了事件冒泡 只指定一个事件处理程序 就可以管理某一类型的所有事件
事件委托的原理
就是事件从最深的节点开始 然后逐步向上传播事件
事件委托的优点:
1 减少内存消耗 不必为大量的元素绑定事件
2 可以为动态添加的元素绑定事件
事件委托的缺点
1 没有冒泡机制的事件无法委托 比如 focus、 blur
2 事件委托有对子元素的查找过程 委托层级过深 可能会有性能问题
3 频繁触发的时如 mousemove、moseout、mouseover等 不适合事件委托
经过事件委托的事件监听函数的this指向的永远是绑定的那个元素 想要知道那个元素触发的事件可以用e.target来获取到
四、什么是闭包
1 如何产生闭包?
内部函数引用了外部函数的数据(变量/函数)
2 闭包是什么?
闭包(closure)就是能够读取其他函数内部变量的函数,在 javascript 中, 只有函数内部的子函数才能读取局部变量,所以闭包可以理解成"定义在一个函数内部的函数"。在本质上,闭包是将函数内部和函数外部链接起来的桥梁。(闭包最典型的引用是实现回调函数(callback))
3、JS中闭包的优缺点及特性
优点:
保护函数内的变量安全
在内存中位置一个变量(用来太多就变成了缺点,占内存)。
逻辑连续,当闭包作为另一个函数调用的参数时,避免你脱离当前逻辑二单独编写额外的逻辑。
方便调用上下文的局部变量。
加强封装性,可以达到对变量的保护作用。
缺点:
常驻内存,会增大内存的使用量,使用不当会造成内存泄露。
还有一个非常严重的问题 那就是内存浪费问题,这个内存浪费不仅仅因为它常驻内存,更重要的是,对闭包的使用不当会造成无效内存的产生
函数执行完成,函数内部局部变量没有释放 占用内存时间会变长。
特性:
- 函数嵌套函数。
- 内部函数可以访问外部函数的变量。
- 参数和变量不会被回收。
五 js数组常用方法
join() 数组转字符串 方法值接受一个参数 默认为逗号分隔符。
splice() 方法向/从数组添加/删除项目,并返回删除的项目。arr.splice(0,1,arr)
indexOf() & lastindexOf() 索引方法 两个都是返回要查找的向所在数组中首次出现的位置,没找到的话就返回-1,一个是从前查找一个是从后查找
改变原数组:
push() & unshift() 添加元素操作 一个是向数组的末尾添加了一个元素 一个是向数组的首位添加了一个元素
shift() & pop() 删除元素操作 分别返回删除的元素一个从第一位删 一个是从末尾删
sort() 数组排序 arr.sort((a, b) => a - b)
reverse() 翻转数组
Es6新增:
find() & findIndex() 根据函数内的判断返回找到的数组内的第一个元素。
find() 返回表达式第一个为true的元素 之后不在调用 没有复合的元素返回undefined
findIndex((currentValue, index, arr) => {}) 用法和find()一样,不同的是不是返回数组内元素,而是返回符合测试函数判断的元素索引值,如果没有符合条件的元素返回 -1。
arr.forEach((currentValue , index , arr) => {}, thisValue) 对数组进行遍历循环,这个方法没有返回值。
arr.map((currentValue, index, arr)=>{}, thisValue) 指“映射”,方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。(不会改变数组长度,和原数组长度保持一致)
arr.filter((currentValue , index , arr) => {}, thisValue) “过滤”功能,方法
创建一个新数组,其包含通过所提供函数实现的测试的所有元素。(可以改变数组长度,不必和原数组长度保持一致)
arr.some((currentValue, index, arr) =>{}, thisValue) 判断数组中是否存在满足条件的项 只要有一项满足条件 就会返回true 不再往下执行
arr.every((currentValue , index , arr) => {}) 判断数组中的每一项是否都满足条件,全部符合就会返回true,否则false。
注意:若收到一个空数组,此方法在一切情况下都会返回 true。
arr.reduce((total , cur , index , arr) => {}, initialValue) 从数组的第一项开始,逐个遍历到最后
arr.reduceRight((total , cur , index , arr) => {}, initialValue) 从数组的最后一项开始,向前遍历到第一项
keys()、values()、entries() 遍历数组方法
keys() 对键名的遍历
values() 对键值的遍历
entries() 是对键值对的遍历。
arr.includes(searchElement , fromIndex) 用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false。
Array.from() 用于类似数组的对象(即有length属性的对象)和可遍历对象转为真正的数组.
Array.of() 将一组值转变为数组,参数不分类型,只分数量,数量为0返回空数组。
arr.fill(value, start, end) 用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
arr.copyWithin(target, start, end) 用于从数组的指定位置拷贝元素到数组的另一个指定位置中,会覆盖原有成员。
六、你对继承怎么看:
1 继承分为两部分
ES5 的继承 分为两部分 首先是属性的继承 属性的继承就是通过
call() apply() bing () 改变this指向。
第二步就是方法的继承 方法的继承就是将子构造函数的原型指向父构造函数的实例的原型
ES6 的继承他就是类的继承 类的继承通过 extends 继承父类
通过 super 关键字将子类的属性或者方法指向父类
七、数组去重的方法有哪些:
- 利用 ES6 Set 去重 (ES6中最常用)
- 利用for嵌套for 然后 splice 去重 (ES5最常用)
- 利用indexOf 去重 判断当前的值在不在整个数组中 如果不在返回-1
- 利用 includes去重 判断当前的值在不在整个数组中 如果在返回true
八、JS的执行机制:
js 是一个单线程的
js 先执行主线程里面的任务 当有异步任务时 提交给对应的异步进程处理
异步任务完毕 推入异步任务队列中
1 主线程执行完毕 查询异步任务队列 去取出一个任务 推入主线程处理 2 重复该动作
这个过程称为事件循环。
九、如何获取对象中所有的属性
-
Objec.keys() 返回一个对象自身可遍历属性名
-
in 运算符和 for…in 循环 in 运算符返回一个布尔值 表示一个对象是否具有某个属性 他不区分该该属性是对象自身的属性还是继承的属性
获得对象的所有可遍历属性(不管是自身的还是继承的) 可以使用 for…in 循环
十、深拷贝浅拷贝的区别?如何实现一个深拷贝?
javascript 中存在两大数据类型:
- 基本类型
- 引用类型
基本类型属性保存在栈内存中
引用类型数据保存再堆内存中 引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中
浅拷贝:
如果是基本数据类型 拷贝的就是基本类型的值 如果是复杂数据类型 拷贝的就是内存地址
- #Object.assign
- Array.prototype.slice() arr.slice(0)
- Array.prototype.concat() arr.concat()
- 使用拓展运算符实现的复制 […arr]
深拷贝:
深拷贝开辟一个新的栈,两个对象属性完全相同,但是对应两个不同的地址,不会改变另一个对象的属性。
常见的深拷贝方式有:
- _.cloneDeep()
- jQuery.extend()
- JSON.stringify() 但是这种方式存在弊端,会忽略undefined、symbol和函数
- 手写循环递归
区别
浅拷贝只值赋值属性指向某个对象的指针 而不复制对象本身,新旧对象还是同享一块内存,修改对象属性会影响原对象。
但深拷贝会另外创建一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
前提为拷贝类型为引用类型的情况下:
浅拷贝是拷贝一层,属性为对象时,浅拷贝是复制,两个对象指向同一个地址
深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址
十一、js 原型链怎么理解?
一个对象所以拥有的属性不仅仅是它本身拥有的属性,他还会从其他对象中继承一些属性,当js在一个对象中找不到需要的属性时,他会找这个对象的父对象上去找,以此类推,这就构成了对象的原型链。 Object.prototype就是原型链的终点了,它的__proto__是null,js查找属性时,如果到这里还没有找到,那就是undefined了。
十二、bind、call、apply 区别?
call、apply、bind 就是改变函数运行时的 this 指向
apply
apply 接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次
当第一个参数为null、undefined的时候,默认指向window(在浏览器中)
call
call 方法的第一个参数也是 this 的指向 后面传入的是一个参数列表 跟apply一样 改变this指向后原函数会立即执行,且次方法只是临时改变this一次
当第一个参数为null、undefined的时候,默认指向window(在浏览器中)
bind
bind方法和call 很相似 第一参数也是this的指向 后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)
改变 this 指向后不会立即执行,而是返回一个永久改变this指向的函数
十三、什么是防抖和节流?有什么区别?如何实现?
本质上是优化高频率执行代码的一种手段
定义
- 节流:n 秒内置运行一次 若在n秒内重复触发只有一次生效。
- 防抖:n 秒后再执行该事件,若在n秒内被重复触发,则重新计时。
相同点:
- 都可以通过使用 setTimeout 实现
- 目的都是,降低回调执行频率,节省计算资源。
不同点:
- 函数防抖,在一段连续操作结束后,处理回调,利用 clearTimeout 和 setTimeout 实现。
- 函数节流,在一段连续操作中,每一段事件只执行一次,频率较高的时间中使用来提高性能。
- 函数防抖关注一定事件连续触发的时间,只在最后执行一次。
- 函数节流一段时间内只执行一次。
十四、Javascript本地存储的方式有哪些?区别及应用场景?
javascript 本地缓存的方法 主要说四种:
- cookie
- sessionStorage
- localStorage
- indexedDB
cookie
Cookie, 类型为[小型文本文件], 指某些网站为了辨别用户身份而存储在用户本地终端上的数据。是为了解决 HTTP 无状态导致的问题。
作为一段一般不超过 4KB 的小型文本数据 他由一个名称 (Name)、一个值(Value)和其他几个用于控制 cookie 有效期、安全性、使用范围的可选属性组成。
但是 cookie 在每次请求中都会被发送,如果不使用 HTTPS 并对其加密,其保存的信息很容易被窃取,导致安全风险。举个例子,在一些使用cookie 保持登录状态的网站上,如果 cookie 被窃取 他人很容易利用你爹cookie来假扮成你登录网站。
localStorage
特点
- 声明周期:持久化的本地存储,除非主动删除数据,否侧数据是永远不会过期的。
- 存储的信息在同一域中是共享的。
- 当本页操作(新增、修改、删除)了 localStorage 的时候,本页面不会触发 srorage 事件,但是别的页面会触发 storage 事件。
- 大小 :5M (跟浏览器厂商有关系)
- localStorage 本质上时对字符串的读取,如果存储内存多的话会消耗内存空间,会导致页面变卡
- 受同源策略的限制
sessionStorage
sessionStorage 和 localStorage 使用方法基本一致,唯一不同的是生命周期,一旦页面(会话)关闭,sessionStorage 将会删除数据
扩展的前端存储方式
indexedDB是一种低级API,用于客户端存储大量结构化数据(包括, 文件/ blobs)。该API使用索引来实现对该数据的高性能搜索
虽然 Web Storage对于存储较少量的数据很有用,但对于存储更大量的结构化数据来说,这种方法不太有用。IndexedDB提供了一个解决方案
优点:
- 储存量理论上没有上限
- 所有操作都是异步的,相比 LocalStorage 同步操作性能更高,尤其是数据量较大时
- 原生支持储存JS的对象
- 是个正经的数据库,意味着数据库能干的事它都能干
缺点: - 操作非常繁琐
- 本身有一定门槛
区别
关于 cookie、sessioStorage、localStorage 三者的区别主要如下:
- 存储大小: cookie 数据大小不能超过 4K,sessionStorage 和 localStorage 虽然也有存储大小的限制,但比 cookie 大得多,可以达到5M或更大
有效时间: - localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
- sessionStorage 数据在当前浏览器窗口关闭后自动删除;
- cookie设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
数据与服务器之间的交互方式,cookie 的数据会自动的传递到服务器,服务器端也可以写 cookie到客户端: sessionStorage 和 localStorage 不会吧自动吧数据发给服务器,仅在本地保存。