记录自己的面试日常(持续更新)
写在前面的话
又到了跳槽的季节,现在也该总结一下自己在前端积累这么多年的一点珍藏的货色了,注意了我主要总结是尽量用自己能表达的想法去说,所有可能没别人总结的那么客观,还有尽量用简短的话简单的思路去表达应该有的意思,方便记忆理解,还有这篇博文我会持续更新的
什么叫优雅降级和渐进增强(这个其实很多的,但是我是不可能去背的,所有尽量用少的话,总结清楚)
.transition{ -webkit-transition: all .5s; -moz-transition: all .5s; -o-transition: all .5s; transition: all .5s; }//渐进增强 .transition{ transition: all .5s; -o-transition: all .5s; -moz-transition: all .5s; -webkit-transition: all .5s; }//优雅降级
优雅降级:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容
渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果.交互等改进和追加功能达到最好的用户体验
jQuery的实现原理
(functon(window,undefined){})(window)
jQuery利用JS函数作用域的特性,采用立即调用表达式包裹了自身,解决命名空间和变量污染问题
window.jQuery=window.$=jQuery
在闭包当中将jQuery和$()绑定到window上,从而jQuery和$暴露为全局变量
jQuery.fn的init方法返回的this就是jQuery对象
jQuery 的属性拷贝(extend)的实现原理是什么,如何实现深拷贝?
浅拷贝(只复制一份原始对象的引用)
- var newObject=$.extend({},oldObject)
深拷贝(对原始对象实行所引用的对象进行递归拷贝)
- var newObject=$.extend(true,{},oldObject)
清除浮动
第一种
overflow:hidden
第二种
.clearfix:after{ content:".", diplay:block; hieght:0; clear:both; visibility:hidden; }
最快速的数组求最大值
var arr=[1,2,12,5,6]; Math.max(...arr);//es6 math.max.apply(null,arr)//es5 apply //for循环 let max=arr[0]; for(let i=0;i<arr.length-1;i++){ max=arr[i]<arr[i+1]?arr[i+1]:arr[i] } //数组sort() arr.sort((num1,num2)=>{return num1-num2<0})//回忆a-b升序b-a降序,同理喔 arr[0] //数组reduce //这个还是需要科普一下 //aray的reduce()把一个函数作用在整个Array的[x1,x2,x3,x4...]上,这个必须接受两个 //参数,reduce()把结果继续和序列的下一个元素做累计计算,怎么感觉有点像map //感觉没有解释清楚,下面给个地址 arr.reduce((num1,num2){return num1>num2?num1:num2})
数组去重
[... new Set([2,"23","2","5",12,5,6,12])]
最快速的方式
- 最简单的方法
function arr1(){ var n=[]; for(var i=0;i<arr.length;i++){ if(n.indexOf(arr[i])==-1){ n.push(arr[i]) } } return n; }
cookie . sessionStorage . localStorage的区别资料
cookie是网站为了标识用户身份而存储在用户本地终端上的数据
cookie数据使用在同源的http请求中携带,会在浏览器和服务器来回传递
webStorage目的:克服cookie带来的一些限制,当数据需要被严格控制在客户端是,不需要持续的将数据发回服务器
webstorage提供两种API:localstorage(本地存储)和sessionStorage
生命周期:
sessionStorage(本地存储)
- 永久的,关闭网页也不会消失,除非主动删除数据
localStorage(会话存储)
- 数据在当前浏览器窗口关闭后自动删除
cookie 设置的cookie过期时间之前一直有效,即使浏览器关闭
sessionStorage(本地存储)和localStoratge(会话存储)不会自动把数据发给服务器,仅仅本地保存
存储大小:
- cookie –>4k
- sessionStorage和localStorage –>5m或更大
javascript有几种类型的值
栈:原始数据类型(undefined,null,Boolean,number,string)
堆:引用数据类型(对象,数组,函数)
区别:存储位置不同
原始类型数据直接存储在栈的简单数据段
- 占据空间小,大小固定,属于被平凡使用数据,所以放在栈中存储
引用数据类型存储在堆中的对象
- 占据空间大,大小不固定,如果存储在栈中,将会影响程序运行的性能
- 引用数据类型在栈中存储了指针,该指针指向该实体的起始地址
- 当解释器寻找引用值时,会首先检索在栈中的地址,取得地址后从堆中获取实体
javascript如何实现继承
原型prototype机制或apply和call方法去实现较简单,建议使用构造函数与原型混合方式。
function Parent(){
this.name = 'wang';
}
function Child(){
this.age = 28;
}
Child.prototype = new Parent();//继承了Parent,通过原型
var demo = new Child();
alert(demo.age);
alert(demo.name);//得到被继承的属性
什么是doctype
DTD就是告诉浏览器我是什么文档类型,用这个来判断我用什么来解析它渲染它
doctype就是通知浏览器哪个DTD和文档类型
<!doctypehtml>
—>HTML5
HTML4.0有两个模式:严格模式和宽松模式
内核的理解
分为两个部分:渲染引擎和js引擎
渲染引擎:负责取得网页的内容(html,css)
js引擎:解析和执行javascript来实现网页的动态效果,但是后来js引擎越来越独立了(V8引擎)
有一个长度100的数组,算前10项的和
var a=[1,2,34,4,5,6,76,7,1,2,3,4,5,6,7]
sun=null;
sun=a.slice(0,10).reduce(function(pre,current){
return pre+current;
})
console.log(sun);//reduce可以看前面最大值
javascript优化
松耦合:当修改一个组件而不需要改其他组件时,就做到松耦合
将js从css中抽出,不要使用css表达式
将css从js中抽出:通过js修改css样式时,使用className或classList
将js从html抽离:从js外置文件
将HTML从js中抽离:不要使用innerHTML使用字符串模板
全局变量
零全局变量(function(){})(window)
单全局变量(jQuery)和命名空间
模块
事件处理
隔离应用逻辑(将应用逻辑和事件处理的代码拆分开)
var MyApplication = {
handleClick: function(event){
this.showPopup(event);
},
showPopup: function(event){
var popup = document.getElementById('popup');
popup.style.left = event.clientX + 'px';
popup.style.top = event.clientY + 'px';
popup.className = 'reveal';
}
};
addListener(element,'click',function(event){
MyApplication.handleClick(event);
});
不要分发事件对象
让事件处理程序使用event对象来处理事件,然后拿到所有需要的数据传到应用逻辑
//改进的做法
var MyApplication = {
handleClick: function(event){
this.showPopup(event.clientX,event.clientY);
},
showPopup: function(x,y){
var popup = document.getElementById('popup');
popup.style.left = x + 'px';
popup.style.top = y + 'px';
popup.className = 'reveal';
}
};
addListener(element,'click',function(event){
MyApplication.handleClick(event);
});
记得在事件处理程序应当在进入应用逻辑之前针对event对象执行任何必要的操作,包括阻止时间冒泡,都应该包含在事件处理程序中
//改进的做法
var MyApplication = {
handleClick: function(event){
event.preventDefault();
event.stopPropagation();
this.showPopup(event.clientX,event.clientY);
},
showPopup: function(x,y){
var popup = document.getElementById('popup');
popup.style.left = x + 'px';
popup.style.top = y + 'px';
popup.className = 'reveal';
}
};
addListener(element,'click',function(event){
MyApplication.handleClick(event);
});
感觉这个需要日积月累,感觉前面是有无数的坑等着你踩先完成功能然后再考虑优化的问题
线程和进程的区别
node进程启动过后默认会创建一个线程,线程用于执行我们的代码
一个进程可以有多个线程,所有进程与线程是包含与被包含的关系
进程(程序):一个静态概念,一个class文件,一个exe文件
线程:是一个程序里面不同的执行路径
二叉树遍历
先序遍历:顺序根左右
中序遍历:顺序左根右
后序遍历:顺序左右根
层序遍历:顺序从上到下从左到右分层遍历
前序遍历:先访问根节点,然后前序遍历左子树,再前序遍历右子树(中左右)
中序遍历:从根节点开始(注意不是先访问根节点),中序遍历根节点的左子树,然后是访问根节点,左后遍历根节点的右子树(左中右)
这里还是要多罗嗦一些东西,因为我有时还是有点不太懂(这样是不是稍微清晰了一点)
中序遍历:BDCAEHGKF
后序遍历:从左到右先叶子后节点的方式遍历访问根节点(左右中)//怎么有点像css遍历从上到下从右到左
层序遍历:从树的第一层,也就是根节点开始访问,从上到下逐层遍历,在同一层中,按从左到右的顺序结构访问
浏览器的渲染原理
当浏览器获取html文件时,会”自上而下”加载,并在加载过程解析渲染
解析:
浏览器会将HTML解析成一个DOM树,DOM树的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点
将CSS解析成CSS Rule Tree
根据DOM树和CSSOM树来构造Rendering Treen,注意:Rendering Tree渲染树并不等同于DOM树,因为一些想header或display:none的东西就没必要放在渲染树中
有了Render Tree,浏览器已经能知道网页中有哪些节点.各个节点的CSS定义以及他们的从属关系,下一步操作称之为Layout就是计算出每个节点在屏幕中的位置
然后就进行绘制,遍历render树,并使用UI后端层绘制每一个节点
终于说到重点了,影响浏览器渲染主要有:reflow(回流)和repaint(重绘)
回流Reflow(渲染机制类)
- DOM结构中的各个元素都有自己的盒子模型,这些需要浏览器根据各种样式计算并根据计算结果将元素放在该出现的位置,这个过程称reflow
触发Reflow
移动DOM
修改CSS
修改网页默认字体
增加删除修改DOM节点
重绘Repaint
- 页面呈现的内容放在页面上
触发Reqaint
DOM改动
CSS改动
尽量避免reflow(回流)
reflow想想怎么可能避免呢?那只能将reflow对性能的影响减到最小
比如需要改变元素的样式,不要通过父级元素影响子元素,最好直接加载子元素
设置style属性改变样式的话,没设置一次都会导致一次reflow,最好就是设置class的方式
避免不必要的复杂的css选择器,尤其是后代选择器(这里肯定会有人反驳了,我用的是less,就看看解析的时候,后代有多长,看着多怕,哥们要不你用sess或者sass,有个属性可以直接跳出选择器
@at-root
less有没有我也不知道)还有就是不要用tables布局
ES6
从数组中移出falsey值
使用Array.filter()删选出falsey值(false,null,0,””,undefined和NaN)
const compact=arr=>arr.filter(Boolean); console.log(compact([0, 1, false, "", 3, "s","e"*23,"a", NaN]));
Ajax
$.ajax({//jQuery
url:"http://www.baidu.com",//请求的url地址
dataType:"json",//返回的数据格式
data:{} //参数
type:"GET"
success:function(data){
//请求成功的请求
}
})
// 1.创建
var ajax = new XMLHttpRequest();
// 2设置
ajax.open('get', 'Ajax_get.php');
// 3.发送
ajax.send(null);
// 4.状态事件
ajax.onreadystatechange = function() {
if (ajax.readyState == 4 && ajax.status == 200) {
// 5.使用返回的数据 修改页面的内容
// responseText 返回的就是一个 字符串
// 我们 在ajax 中 如果 是通过 ajax.responseText 获取到的 统统都是字符串
console.log(ajax.responseText);
}
}
var ajax = new XMLHttpRequest();
// 使用post请求
ajax.open('post','ajax_post.php');
// 如果 使用post发送数据 必须 设置 如下内容
// 修改了 发送给 服务器的 请求报文的 内容
// 如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定您希望发送的数据:
ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// 发送
// post请求 发送的数据 写在 send方法中
// 格式 name=jack&age=18 字符串的格式
ajax.send('name=jack&age=998');
// 注册事件
ajax.onreadystatechange = function () {
if (ajax.readyState==4&&ajax.status==200) {
console.log(ajax.responseText);
}
}