面试小结
这是我参加的第二次面试,两次面试大同小异,但这次面试问的问题更基础简单一些。关键是碰到了很好的面试官,说话也很接地气。问到我一时半会回答不上来的问题的时候给了我充分的时间去想去思考,有的问题我回答的不完整,他也给了我相对完整的答案。有两三个问题没有回答上来,后来也很详细认真地帮我解答了。这次面试体验极佳!
面试问题
重绘和重排
重排:当渲染树的一部分必须更新并且节点的尺寸发生了变化,浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。
重绘:是在一个元素的外观被改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。
重绘不一定需要重排,重排必然会导致重绘。
导致重排的原因:
- 添加、删除可见的dom
- 元素的位置改变
- 元素的尺寸改变(外边距、内边距、边框厚度、宽高等几何属性)
- 页面渲染初始化
- 浏览器窗口尺寸改变
本地存储方式localStorage和sessionStorage(cookie提及一下)
Cookie、SessionStorage、 LocalStorage都是浏览器的本地存储。 它们的共同点:都是存储在浏览器本地的
它们的区别:cookie是由服务器端写入的,而SessionStorage、LocalStorage都是由前端写入的,cookie的生命周期是由服务器端在写入的时候就设置好的,LocalStorage是写入就一直存在,除非手动清除,SessionStorage是页面关闭的时候就会自动清除。cookie的存储空间比较小大概4KB,SessionStorage、LocalStorage存储空间比较大,大概5M。Cookie、SessionStorage、LocalStorage数据共享都遵循同源原则,SessionStorage还限制必须是同一个页面。在前端给后端发送请求的时候会自动携带Cookie中的数据,但是SessionStorage、LocalStorage不会。
由于它们的以上区别,所以它们的应用场景也不同,Cookie一般用于存储登录验证信息SessionID或者token,LocalStorage常用于存储不易变动的数据,减轻服务器的压力,SessionStorage可以用来检测用户是否是刷新进入页面,如音乐播放器恢复播放进度条的功能。
闭包和作用域
一个函数和词法环境的引用捆绑在一起,这样的组合就是闭包(closure)。一般就是一个函数A,return其内部的函数B,被return出去的B函数能够在外部访问A函数内部的变量,这时候就形成了一个B函数的变量背包,A函数执行结束后这个变量背包也不会被销毁,并且这个变量背包在A函数外部只能通过B函数访问。
闭包形成的原理:作用域链,当前作用域可以访问上级作用域中的变量 闭包解决的问题:能够让函数作用域中的变量在函数执行结束之后不被销毁,同时也能在函数外部可以访问函数内部的局部变量。
闭包带来的问题:由于垃圾回收器不会将闭包中变量销毁,于是就造成了内存泄露,内存泄露积累多了就容易导致内存溢出。
闭包的应用,能够模仿块级作用域,能够实现柯里化,在构造函数中定义特权方法、Vue中数据响应式Observer中使用闭包等。
一段程序代码中所用到的名字并不总是有效的和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
作用域分为全局作用域和局部作用域。全局作用域作用范围为整个script标签,或者是一个单独的js文件;局部作用域的作用范围为函数内部,这个代码中的名字只在函数内部起效。
执行效率方面,全局变量在关闭浏览器后才会销毁,比较占用内存资源;局部变量在程序执行完后就会销毁,比较节约内存资源。
在ES6后,JS中有了块级作用域的说法,即被花括号围起来的部分。
这里还要注意一个作用域链的概念:只要是代码,就至少有一个作用域,而作用域链我们可以理解成是写在函数内部的局部作用域,即如果函数中还有函数,纳闷在这个作用域中就又可以诞生一个作用域。根据“内部函数可以访问外部函数变量”的机制,用链式查找决定哪些数据能被内部函数访问,这就称为作用域链。
原型和原型链以及原型链顶端是什么
原型是一个可以被复制的一个类,通过复制原型可以创建一个一模一样的新对象,也可以说原型就是一个模板,更准确地说是一个对象模板;
原型链是原型对象创建和过程中的历史记录,当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构。
函数的prototype是一个在函数声明阶段就会产生的对象(prototype只有函数才会有),这个对象只有两个属性constructor和__proto__,其中__proto__指向了我们原型链的顶点Object.prototype。constructor指向函数本身,里面包括了函数一些基本描述信息比如函数名称,参数个数等。
get和post的区别
Web浏览器通常会使用HTTP(超文本传输协议)的两种方法(GET方法和POST方法)其中之一来与服务器通信。这两种方法会以不同方式传递信息,将数据发送到服务器。
在GET方法中,数据将作为URL的参数发送,这些参数通常是由&符号分隔的名称和值对的字符串。由于GET方法发送的数据显示在URL中,因此可以使用特定查询字符串值为页面添加书签。GET方法不适合传递用户名和密码等敏感信息,因为这些信息在URL查询字符串中完全可见,并且可能作为访问页存储在客户端浏览器的内存中。由于GET方法将数据分配给服务器环境变量,因此URL的长度是有限的。因此,要发送的总数据存在限制。
在POST方法中,数据作为包在与处理脚本的单独通信中发送到服务器;通过POST方法发送的数据在URL中不可见。
POST方法适用于可以传递大量信息的情况。当服务器通过采用POST的表单接收请求时,它在对URL进行请求之后立即传输表单输入的所有相关信息。它比GET更安全,因为用户输入的信息在URL查询字符串或服务器日志中永远不可见。可以传递的数据量有一个更大的限制,一个人可以使用POST发送文本数据和二进制数据(上传文件)。由于POST方法发送的数据在URL中不可见,因此无法使用特定查询为页面添加书签。
请说一下CSS尺寸设置的单位
px:pixel像素的缩写,绝对长度单位,它的大小取决于屏幕的分辨率,是开发网页中常常使用的单位。
em:相对长度单位,在 font-size中使用是相对于父元素的字体大小,在其他属性中使用是相对于自身的字体大小,如width。如当前元素的字体尺寸未设置,由于字体大小可继承的原因,可逐级向上查找,最终找不到则相对于浏览器默认字体大小。
rem:相对长度单位,相对于根元素的字体大小,根元素字体大小未设置,使用浏览器默认字体大小。 vw:相对长度单位,相对于视窗宽度的1%。 vh:相对长度单位,相对于视窗高度的1%。
vmin:相当于视窗短边长度的1%。vmax:相当于视窗长边高度的1%。
防抖和节流的思路
防抖就是,不管你触发了几次,我只看你最后触发的那一次,并且在若干时间后去执行此次事件。
节流会强制执行一个函数在一段时间内可以被调用的最大次数。如“最多每 100 毫秒执行一次此函数”。
防抖强制一个函数在一段时间内没有被调用之前不会被再次调用。如“仅当 100 毫秒过去了而没有被调用时才执行此函数”。
实现左右两栏布局的方法有哪些
利用float、定位position、定位flex、margin负值、grid布局、table布局。
具体可以看这篇文章,写的很细。https://blog.csdn.net/qq_43456687/article/details/124124380
JS中的数据结构有哪些
JS数据类型分为两类:一类是基本数据类型,也叫简单数据类型,包含7种类型,分别是Number、String、Boolean、BigInt、Symbol、Null、Undefined。另一类是引用数据类型也叫复杂数据类型,通常用Object代表,普通对象,数组,正则,日期,Math数学函数都属于Object。
数据分成两大类的本质区别:基本数据类型和引用数据类型它们在内存中的存储方式不同。
基本数据类型是直接存储在栈中的简单数据段,占据空间小,属于被频繁使用的数据。
引用数据类型是存储在堆内存中,占据空间大。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,当解释器寻找引用值时,会检索其在栈中的地址,取得地址后从堆中获得实体。
ES6中引入了一种新的原始数据类型symbol,表示独一无二的值,可以用来解决命名冲突的问题,它不能够与其他数据进行运算。
若代码为 log.console(a);var a = 1; 会打印什么?若代码为log.console(a);{var a = 1;},又会输出什么?
前者为undefined,后者会报错。(此处知识点涉及变量提升和作用域)
CSS中选择器有哪些?
标签选择器,类选择器,id选择器,伪类选择器
dom节点的操作有哪些?
1.访问/获取节点
document.getElementById(id); //返回对拥有指定id的第一个对象进行访问 document.getElementsByName(name); //返回带有指定名称的节点集合 注意拼写:Elements document.getElementsByTagName(tagname); //返回带有指定标签名的对象集合 注意拼写:Elements document.getElementsByClassName(classname); //返回带有指定class名称的对象集合 注意拼写:Elements
2.创建节点/属性
document.createElement(eName); //创建一个节点 document.createAttribute(attrName); //对某个节点创建属性 document.createTextNode(text); //创建文本节点
3.添加节点
document.insertBefore(newNode,referenceNode); //在某个节点前插入节点 parentNode.appendChild(newNode); //给某个节点添加子节点
4.复制节点
cloneNode(true | false); //复制某个节点 参数:是否复制原节点的所有属性
5.删除节点
parentNode.removeChild(node); //删除某个节点的子节点 node是要删除的节点 注意:为了保证兼容性,要判断元素节点的节点类型(nodeType),若nodeType==1,再执行删除操作。通过这个方法,就可以在 IE和 Mozilla 完成正确的操作。
6.修改文本节点
appendData(data); 将data加到文本节点后面 deleteData(start,length); 将从start处删除length个字符 insertData(start,data); 在start处插入字符,start的开始值是0; replaceData(start,length,data); 在start处用data替换length个字符 splitData(offset); 在offset处分割文本节点 substringData(start,length); 从start处提取length个字符
7.属性操作
getAttribute(name) //通过属性名称获取某个节点属性的值 setAttribute(name,value); //修改某个节点属性的值 removeAttribute(name); //删除某个属性
8.查找节点
parentObj.firstChild; //如果节点为已知节点的第一个子节点就可以使用这个方法。此方法可以递归进行使用 parentObj.firstChild.firstChild..... parentObj.lastChild; //获得一个节点的最后一个节点,与firstChild一样也可以进行递归使用 parentObj.lastChild.lastChild..... parentObj.childNodes; //获得节点的所有子节点,然后通过循环和索引找到目标节点
9.获取相邻的节点
curtNode.previousSibling; //获取已知节点的相邻的上一个节点 curtNode.nextSlbling; // 获取已知节点的下一个节点
10.获取父节点
childNode.parentNode; //得到已知节点的父节点
11.替换节点
replace(newNode,oldNode);
(内容来自:https://www.cnblogs.com/JanySu/p/5278542.html)
JS中如何判断变量类型
JavaScript有4种方法判断变量的类型,分别是typeof、instanceof、Object.prototype.toString.call()(对象原型链判断方法)、 constructor (用于引用数据类型)
typeof:常用于判断基本数据类型,对于引用数据类型除了function返回’function‘,其余全部返回’object'。
instanceof:主要用于区分引用数据类型,检测方法是检测的类型在当前实例的原型链上,用其检测出来的结果都是true,不太适合用于简单数据类型的检测,检测过程繁琐且对于简单数据类型中的undefined, null, symbol检测不出来。
constructor:用于检测引用数据类型,检测方法是获取实例的构造函数判断和某个类是否相同,如果相同就说明该数据是符合那个数据类型的,这种方法不会把原型链上的其他类也加入进来,避免了原型链的干扰。
Object.prototype.toString.call():适用于所有类型的判断检测,检测方法是Object.prototype.toString.call(数据) 返回的是该数据类型的字符串。
这四种判断数据类型的方法中,各种数据类型都能检测且检测精准的就是Object.prototype.toString.call()这种方法。
instanceof的实现原理:验证当前类的原型prototype是否会出现在实例的原型链__proto__上,只要在它的原型链上,则结果都为true。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,找到返回true,未找到返回false。
Object.prototype.toString.call()原理:Object.prototype.toString 表示一个返回对象类型的字符串,call()方法可以改变this的指向,那么把Object.prototype.toString()方法指向不同的数据类型上面,返回不同的结果
浅拷贝的方法
const obj = { name:'小弟', age:16, }
方法有:
slice()
concat()
Object.assign(target, ...sources)
{...obj} 和 [...arr]
循坏push