- 赋值、深拷贝和浅拷贝

-
赋值:复制指针
-
浅拷贝:创建一个新对象,将对象或数组中的基本类型直接复制给新的对象或数组,引用类型复制指针。
function shallowCopy(obj){ var newObj = obj.constructor === Array ? [] : {}; for(let i in obj){ if(obj.hasOwnProperty(i)){ newObj[i] = obj[i]; } } return newObj; } -
深拷贝:在浅拷贝的基础上做递归,直到最深层全部复制完毕。
-
深拷贝实现方法:
-
递归
function deepClone(obj){ var newObj = obj.constructor === Array ? [] : {}; for(let keys in obj){ if(obj.hasOwnProperty(keys)){//能够排除继承来的原型链上的属性 if(typeof obj[keys] === 'object'){ newObj[keys] = obj[keys].constructor === Array ? [] : {}; newObj[keys] = deepClone(obj[keys]); } else{ newObj[keys] = obj[keys]; } } } return newObj; } -
JSON.parse(JSON.Stringfy(obj))缺点:不能处理函数对象和正则对象
function deepClone(obj){ var newObj = {}; return newObj = JSON.parse(JSON.Stringfy(obj)); }
-
-
浏览器是怎么渲染页面的
- 通过HTML解析器解析HTML文档,构建一个DOM Tree,同时通过CSS解析器解析HTML中存在的CSS,构建Style Rules,两者结合形成一个Attachment。
- 通过Attachment构造出一个呈现树(Render Tree)
- Render Tree构建完毕,进入到布局阶段(layout/reflow),将会为每个阶段分配一个应出现在屏幕上的确切坐标。
- 最后将全部的节点遍历绘制出来后,一个页面就展现出来了。
引擎为了力求显示的及时,会在文档请求不完全的情况下就开始渲染页面,同时,如果在解析的过程中遇到script的时候,文档的解析将会停止下来,立即解析执行脚本,如果脚本是外部的,则会等待请求完成并解析执行。所以,为了不阻塞页面地呈现,一般会把script脚本放在文档的最后。
解决方案:
- 在最新的HTML4和HTML5规范中,也可以将脚本标注为defer,这样就不会停止文档解析,而是等到解析结束后才执行。
- HTML5 增加了一个选项,可将脚本标记为
async,以便由其他线程解析和执行。
作者:
elliott_hu链接:https://segmentfault.com/a/1190000013522717 -
css实现左右固定宽度 中间自适应-
父级div包3个子div,父级设置
display:flex,对左右两边的div设置固定width,中间的要设置width:100%或者flex:1 (flex-grow:1)flex属性是flex-grow,flex-shrink,flex-basis,默认值为0,1,auto flex-grow:定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大 flex-shrink:定义了缩小比例,默认为1,空间不足则项目缩小 flex-basis定义了在分配多余空间之前,项目占据的主轴空间,默认为auto,即本来大小 -
利用浮动元素float,让左右元素浮动,缺点是中间元素必须置于二者之后
左项目左浮动,右项目右浮动,左右元素需要定义width,height。 中间元素需要定义height。 <div class="left"></div> <div class="right"></div> <div class="center"></div> center占据文档流位置,所以一定要放在最后,左右两个元素位置没有关系。 当浏览器窗口很小的时候,右边元素会被击倒下一行。 -
利用绝对定位,父元素相对定位,左右元素绝对定位,中间元素用margin给左右元素留出位置
<div class="father"> <div class="left"></div> <div class="right"></div> <div class="center"></div> </div> <style> .father{ width: 100%; height: 100%; position: relative; } .left{ position: absolute; left: 0; top: 0; width: 400px; height: 200px; } .right{ position: absolute; top: 0; right: 0; width: 400px; height: 200px; } .center{ margin: 0 400px; height: 200px; } </style>
-
-
合并两个有序数组(去重)
var merge = function(arr1, m, arr2, n){ let len1 = m-1; let len2 = n-1; let len = m + n - 1; while(len2 >= 0){ if(len1 < 0){ arr1[len--] = arr2[len2--] continue; } arr1[len--] = arr1[len1] >= arr2[len2] ? arr1[len1--] : arr2[len2--]; } return [...new Set(arr1)]; } -
求两个数组的交集 返回一个包含所有交集元素的数组
var intersection = function(arr1, arr2){ return [...new Set(arr1.filter((item) => arr2.includes(item)))] } -
宏任务和微任务有哪些
首先
js是同步执行的,但对于某些执行时间比较长的函数或代码来说,所有之后的代码都需等待直至它执行完,所以加入了回调函数的概念,进行异步操作。所以任务可以简单分为同步任务和异步任务。首先我们进行顺序执行,遇到异步操作时,等异步操作结束之后,若同步任务还未执行完,则需等待至同步任务执行完再执行回调函数。
宏任务和微任务的执行顺序:在执行宏任务时若碰到微任务则执行所有的微任务,直至执行完毕再执行下一个宏任务。
任务 函数 微任务 promise/process.nextTick/MutationObserver宏任务 setTimeout/setInterval/setImmediatepromise:一个对象,获取异步操作的消息process.nextTick:类似于setTimeout,node层面MutationObserver:监听目标DOM节点
两者都代表主线程完成后立即执行,其执行结果是不确定的。
setTimeout回调函数执行结果在前的概率更大些,这是因为他们采用的观察者不同,setTimeout采用的是类似IO观察者,setImmediate采用的是check观察者,而process.nextTick()采用的是idle观察者。 -
es6的新特性
class,constructor,export,import let(只在声明的代码块有效,且不会向var那样对变量进行提升) const(只读的常量) => 反引号`` Set类似于数组,但是成员的值都是唯一的,没有重复的值。 Map类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键 Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。//...解构赋值 let [head, ...tail] = [1, 2, 3, 4]; head // 1 tail // [2, 3, 4] new Set(arr) [...new Set(arr)] let { bar, foo } = { foo: "aaa", bar: "bbb" }; foo // "aaa" bar // "bbb" // assign方法对象的合并,将obj1,obj2合并到obj中 Object.assign(obj,obj1,obj2) -
箭头函数和普通函数区别
-
this的指向问题
-
基本类型和引用类型
-
css布局(这里面试官让说弹性盒子布局) -
em和rem区别rem=root of emem=16px(一般) -
css权重(选择器优先级)!important>内联样式>id选择器>class选择器>伪类| -
重绘和重排
-
vuex在项目中的使用场景:(一般在数据和组件分离,分别处理的场景下使用)- 涉及非父子关系(兄弟关系、祖孙关系等)组件之间的数据交互
- 组件会被销毁
- 组件基于数据而创建,数据变化会影响到多个组件
- 多对多事件——多处触发,影响多处
-
父子组件通信
Prop, $emit, .sync, $attrs & $listeners, Vuex等 -
页面跳转传值(路由跳转)
-
url后带参数 -
sessionStorage和localStoragewindow.localStorage.setItem('data','1'); window.localStorage.getItem('data')
-
-
项目中如何解决跨域(答的是
cors跨域资源共享) -
事件委托和事件冒泡
-
事件捕获是从外层元素到目标元素的过程
-
事件冒泡是从目标元素到外层元素的过程
-
-
vue生命周期-
beforeCreate:在页面创建之前调用 -
created:页面创建后被立即调用,已完成数据观测,属性和方法的运算,watch/event事件回调。挂载阶段还没开始,$el属性目前不可见 -
beforeMount:在挂载开始之前被调用,相关的渲染函数首次被调用 -
mounted:挂载成功立即调用 -
beforeUpdate:数据更新时调用 -
updated:dom已经更新,组件更新完毕 -
activated:组件激活时调用 -
deactivated:组件停用时调用 -
beforeDestroy:实例销毁之前调用 -
destroyed:实例销毁之后调用,调用后实例绑定的所有东西都会解绑,所有的时间监听都会移除 -
errorCaptured:捕获来自子组件的错误时调用
-
-
post的几种提交数据方式
-
application/x-www-form-urlencoded:原生form表单 -
multipart/form-data:使用表单上传文件时 -
application/json:JSON字符串 -
text/html:html -
raw:text/json/xml/html
-
-
for each、for in、for of的区别
-
forEach:arr.forEach()遍历数组元素进行操作,不接受return -
for in:取的是key -
for of:遍历的是value
-
-
vuex的核心作用 -
vue的底层原理:MVVM -
css加载会造成阻塞吗 -
从输入
url到页面加载完成会发生什么?-
拿到
url后,通过DNS解析拿到ip地址 -
进行
TCP连接,三次握手 -
发送
HTTP请求 -
服务端处理请求并返回
HTTP报文 -
浏览器解析渲染页面
-
连接结束,四次挥手
-
-
建立
TCP连接的正确流程(连接时的三次握手):客户端向服务器端发送SYN包;服务端向客户端发送SYN+ACK;客户端回复ACK。 第一次,本机将标识位 SYN 置为 1, seq = x(Sequence number)发送给服务端。此时本机状态为SYN-SENT 第二次,服务器收到包之后,将状态切换为SYN-RECEIVED,并将标识位 SYN 和 ACK都置为1, seq = y, ack = x + 1, 并发送给客户端。 第三次,客户端收到包后,将状态切换为ESTABLISHED,并将标识位ACK置为1,seq = x + 1, ack = y + 1, 并发送给服务端。服务端收到包之后,也将状态切换为ESTABLISHED。 -
断开时的4次挥手:
客户端向服务器端发送FIN;服务器端回复ACK,并进入wait状态;服务器端确认并发送FIN;客户端回复ACK. 第一次,客户端发送一个FIN置为1的包,ack = y, seq = x + 1,此时客户端的状态为 FIN_WAIT_1。 第二次,服务端收到包后,状态切换为CLOSE_WAIT发送一个ACK为1的包, ack = x + 2。客户端收到包之后状态切换为FNI_WAIT_2。 第三次,服务端处理完任务后,向客户端发送一个 FIN包,seq = y; 同时将自己的状态置为LAST_ACK。 第四次,客户端收到包后状态切换为TIME_WAIT,并向服务端发送ACK包,ack = y + 1,等待2MSL后关闭连接。 -
原型、原型链、作用域、作用域链、继承、闭包
-
原型:用来生产实例对象的模型
-
原型链:实例模型有个指针指向原型对象,原型对象有个指针指向构造函数,这就形成了一条原型链,最终指向
null -
作用域:变量或函数作用的范围
-
作用域链:内部函数一直向外寻找变量的路径
-
闭包:内部函数使用外部函数的变量和方法
//闭包的运用(面试题) var go = function (a) { var str = 'go'; var add0 = function (a) { str += 'o'; return a ? str += a : add0;// 巧妙使用 } return a ? str += a : add0;// 巧妙使用 } console.log(go('l'));//gol console.log(go()('l'));//gool console.log(go()()('l'));//goool -
继承:一个对象可以共享父级对象的一些属性而不需要去重复定义
-
继承的方式:juejin.cn/post/684490…
-
组合继承:在子类函数中调用父类函数并传参。子类的构造函数定义为父类的构造函数,继承父类所有属性。缺点:子类的原型上多了不需要的父类属性,造成内存上的浪费
function Parent(name, age) { this.name = name; this.age = age; } function child(name, age, sex) { Parent.call(this, name, age); this.sex = sex; } child.prototype = new Parent() var c1 = new child('zenquan', '23', 'M') console.log(c1) -
class继承:extends,子类的构造函数中放入需要的参数,super方法中放入父类存在的参数
class parent { constructor(name, age) { this.name = name; this.age = age; } getName() { return this.name; } } class child extends parent { constructor(name, age, sex) { super(name, age); this.sex = sex; } }
-
-
-
vue双向绑定原理 -
vue和react区别 -
如何判断数据类型
-
css权重!important>行内样式>id选择器>类选择器>标签选择器>通配符>继承 -
几种width
clientWidthoffsetWidthscrollTopscrollHeight宽度+ padding宽度+ padding+border被卷上去的距离 自身实际的高度(不包括边框) -
可以被继承的
css属性:文本(font-),颜色(背景颜色不可以!),列表(list-style-type),元素可见性visibility