JS 的基本数据类型和引用数据类型
- 基本(原始)数据类型: number、string、boolean、undefined, null, symbol
- 引用数据类型: Object、Function、Array
浅拷贝和深拷贝的区别
- 浅拷贝:浅拷贝对内存地址的复制,让目标对象指针和源对象指向同一片内存空间。
- 深拷贝:深拷贝是指拷贝对象的具体内容,其内存地址是自主分配的,拷贝结束之后俩个对象虽然存的值是一样的,但是内存地址不一样,俩个对象互相不影响,互不干涉。
JSON.parse(JSON.stringify());
//使用递归完成深拷贝对象
function shenCopy(obj) {
//创建参数的构造函数对象
var result = obj.constructor();
if (typeof obj !== Object) {
//当传入参数不为Object类型时,直接返回该参数
return obj;
} else {
for (let key in obj) {
//递归核心:将嵌套对象递归得到的返回值赋予新建的构造对象
result[key] = shenCopy(obj[key]);
}
}
return result;
}
什么是JS变量提升 与 块级作用域
- 变量提升:就是会把变量定义提升到当前作用域的最上面
- 块级作用域:JS 中作用域有:全局作用域、函数作用域。没有块作用域的概念。ES6中新增了块级作用域。块作用域由 { } 包括,if 语句和 for 语句里面的{ }也属于块作用域。在外边不能调用块作用域里边定义的变量
作用域
- 全局作用域:任何地方都能访问到的对象拥有全局作用域
- 局部作用域:一般只在固定的代码片段中可访问,例如函数作用域
原型链
- 什么是原型:每个构造函数都有一个prototype属性,这个属性指向一个对象,即原型对象 原型对象默认拥有一个constructor(康斯托可托)属性,指向它的那个构造函数
- 什么是原型链:当访问对象上得属性时,会首先查找该对象是否含有该属性,如果没有就会访问proto看看它的原型对象上有没有,如果还没有会继续沿着proto向上寻找,直到指向顶端null(都没有返回undefined),即为原型链
javascript的同源策略(跨域问题)
- 跨域是什么 :实际上就是一个网站不能执行其他网站上的网址,是由浏览器同源策略造成的,是浏览器对js施加的安全限制,所谓同源,实际上是指域名,协议,端口都相同,也就是说当,域名或者协议,或者端口不同的时候,就是跨域
前端如何实现跨域
- JSONP原理:利用script标签加回调的方式。缺点是仅支持get方法具有局限性
var script = document.createElement("script");
script.type = "text/javascript";
// 传参并指定回调执行函数为onBack
script.src = "http://www.demo2.com:8080/login?user=admin&callback=onBack";
document.head.appendChild(script);
// 回调执行函数
function onBack(res) {
alert(JSON.stringify(res));
}
- Nginx:浏览器在访问受限时,可通过不受限的代理服务器访问目标站点。proxy代理是前端用的最多的解决跨域的方法
- core原理:
实现CORS通信的关键是服务器,需要在服务器端做一些小小的改造。只要服务器实现了CORS接口,就可以跨源通信。
说说this指向call、apply、bind的区别
- 前两个可以自动执行,bind不会自动执行,主要手动调用
- call、bind与apply的区别:前两个都有无数个参数,apply只有两个参数,且第二个参数为数组
说说你对闭包的了解
-
特性:
- 函数嵌套函数
- 函数内部可以引用函数外部的变量和参数
- 参数和变量不会被垃圾回收机制回收
-
优点
- 保护函数内的变量安全,实现封装,防止变量流入其他环境发生命名冲突
- 在内存中维持一个变量,可以做缓存(使用过多消耗内存)
- 匿名自执行函数可以减少内存消耗
-
缺点
- 常驻内存会增大内存使用量,使用不当会造成内存泄漏。
- 闭包对脚本性能具有负面影响,包括处理速度和内存消耗
垃圾回收机制
- 引用计数:通过为每个对象维护一个计数器来判断对象是否被引用,当引用计数器为0时,对象被回收
- 优点:发现垃圾会立即回收,最大减少程序栈
- 缺点:无法回收循环引用对象,监控数据计算所需时间较长
- 标记清除:标记清除的原理是可达性,从根结点遍历通过标记所有活动对象,然后清除未被标记的对象。
- 优点:标记清除可以解决循环引用问题
- 缺点:标记清除需要遍历整个算法图,在大型程序中可能会产生延迟和卡顿
javascript 如何实现继承
- 原型链继承
- 构造函数继承
- 原型式继承
- 组合继承
- 寄生式继承
- 寄生组合继承
http请求过程
浏览器发起请求->服务器对浏览器进行应答,响应头信息和浏览器所需的内容-> 关闭TCP连接或保持-> 浏览器得到数据数据进行操作。
三次握手和四次挥手
- 三次握手的过程
- 第一次握手:客户端给服务端发送一个SYN报文给对方
- 第二次握手:服务器端收到客户端的SYN报文之后,会给客户端发送一个SYN加ACK的报文,以示传达确认信息
- 第三次握手:客户端收到服务器端SYN报文后,会发送一个ACK报文,表示已经收到了服务端的SYN报文
- 四次握手的过程
- 第一次挥手:主动关闭方发送一个FIN,用来关注主动方到被动关闭方的数据传送,也即是主 动关闭方告诫被动关闭方:我已经不会再给你发数据了(在FIN包之前发送的数据,如果没有 收到对应的ACK确认报文,主动关闭方依然会重发这些数据)。但是,此时主动关闭方还可 以接受数据
- 第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号收到序号 +1(与SYN相同,一个 FIN占用一个序号)
- 第三次挥手:被动关闭方发送一个 FIN。用来关闭被动关闭方到主动关闭方的数据传送,也 就是告诉主动关闭方,我的数据也发送完了,不会给你发送数据了
- 第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1, 至此,完成四次挥手
ES6有哪些新特性
1、let 和 const let //表示申明变量。const 表示申明常量 常量定义了就不能改了。对象除外,因为对象指向的地址没变。const在申明是必须被赋值。 两者都为块级作用域。
2、模板字符串
3、解构
4、函数的默认值
5、Spread / Rest 操作符 //三个点…
6、箭头函数
7、for of //遍历的是键值对中的值
8、for in //遍历的是键值对中的键
9、class类//原型链的语法糖表现形式
10、导入导出 //导入improt 导出export default
11、promise //Promise 用于更优雅地处理异步请求。
12、async/await //比promise更好的解决了回调地狱
13、Symbol //新的基本类型
14、Set集合 //存储任何类型的唯一值,即集合中所保存的元素是不重复的。类数组结构。 let arrNew = new Set(待去重的数组)
微任务和宏任务的区别
- 宏任务包括:setTimeout setInterval Ajax DOM事件
宏任务是由宿主(浏览器、Node)发起的,宏任务,可以理解为每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行).进程的切换肯定是宏任务,因为需要花费大量的资源
- 微任务包括:Promise async/await 等…
微任务是由JS引擎发起的,微任务,可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。线程的切换是微任务,因为只需要在同一个进程中切换就可以了
请说一下你用过的浏览器存储,并说出它们的区别
- sessionStorage:数据只存在于会话期间
- localStorage:数据永久存储
- cookie:数据默认会话结束时过期,但可以设置过期时间,在请求服务端,浏览器会默认把cookie数据发送给服务器,cookie能存放的数据相对较小
for循环 与 forEach循环的区别?
- for循环中可以使用break、continue不用使用return 因为它有循环体,且不是函数;
- forEach循环不能使用break、continue,可以return,因为它执行的是函数;
请解析一下数组map、filter, reduce三个方法的作用
- map()方法:把回调函数中返回的值,作为一个新数组返回
- filter()方法:返回符合回调函数中条件的元素,形成一个新数组
- reduce()方法:对数组中元素进行从左到右的累计,并返回最终结果
dom事件委托什么原理,有什么优缺点
事件委托原理: 事件冒泡机制(把子元素的事件行为 委托给 父级元素执行优点)
- 优点:
- 可以大量节省内存占用,减少事件注册
- 可以实现当新增子对象时,无需再对其进行事件绑定
- 缺点:
- 如果把所有事件都用事件代理,可能会出现事件误判
Javascript的事件流模型都有什么
-
事件冒泡:事件逐级向上传播
阻止事件冒泡:e.stopPropagation() -
事件捕捉:事件逐级向下传播,一直到最具体的
阻止事件捕捉:return false 或者 ev.prevent Default() -
DOM事件流:三个阶段:事件捕捉,目标阶段,事件冒泡
判断Array类型的几种方式
[ ] instanceof Array
[ ].constructor === Array
Object.prototype.toString.call([]) === '[object Array]'
Array.isArray([])