各公司前端面试题总结(一)

一、CSSposition中absolute和relative定位
positive定位有:static、inherit(从父元素继承positive属性的值)、absolute、relative、fixed
1、absolute是相对于浏览器进行定位,但是当给其父元素设置relative定位后,该子元素的absolute定位就是相对于父元素的
2、relative相对的是自身定位,其相对的是自身进行偏移。
3、两者最核心的区别在于:absolute不受父元素里的其他元素影响,而relative会受到父元素里的其他元素影响。

二、display:none和visibility:hidden
1、display:none是隐藏元素但是不占据空间,不会影响页面布局,浏览器也不会再解析该元素。页面也会产生回流(当页面中的一部分元素需要改变规模尺寸、布局、显示隐藏等,页面重新构建,此时就是回流。所有页面第一次加载时需要产生一次回流)
2、a)visibility:hidden是隐藏元素但依然会占据空间,也会影响页面布局,浏览器依然会解析该元素,但是页面不会产生回流。b)visibility具有继承性,给父元素设置visibility:hidden;子元素也会继承这个属性。c)visibility: hidden不会影响计数器的计数
三、强制缓存与协商缓存及协商缓存的控制
浏览器缓存(Brower Caching)是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。
1、浏览器缓存的优点有:

  • 减少了冗余的数据传输,节省了网费
  • 减少了服务器的负担,大大提升了网站的性能
  • 加快了客户端加载网页的速度

2、强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的network选项中可以看到该请求返回200的状态码;
3、协商缓存:向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header通知浏览器从缓存中读取资源;
4、两者的共同点是,都是从客户端缓存中读取资源;区别是强缓存不会发请求,协商缓存会发请求
缓存 获取资源形式 状态吗 发送请求到服务器
强缓存 从缓存取 200(from cache) 否,直接从缓存取
协商缓存 从缓存取 304(not modified) 是,通过服务器告知浏览器缓存是否可用
5、强缓存如何重新加载缓存缓存过的资源:通过更新页面中引用的资源路径,让浏览器主动放弃缓存,加载新资源。

四、react虚拟dom和react diff
操作dom慢,是因为操作这个对象后,会触发浏览器的一些行为
例如:布局(layout)和绘制(paint)
如下的操作会打破常规,并触发浏览器执行layout:
· 通过js获取需要计算的DOM属性
· 添加或删除DOM元素
· resize浏览器窗口大小
· 改变字体
· css伪类的激活,比如:hover
· 通过js修改DOM元素样式且该样式涉及到尺寸的改变

React.js 相对于直接操作原生DOM有很大的性能优势, 很大程度上都要归功于virtual DOM的batching 和diff。batching把所有的DOM操作搜集起来,一次性提交给真实的DOM。Diff算法通过对比新旧虚拟DOM树记录之间的差异
Virtual DOM 算法。包括几个步骤:

  1. 用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中

  2. 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异

  3. 把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了
    虚拟DOM需要计算的属性相对原生而言会少很多,这样效率就很快,每次操作之后先修改虚拟dom结构,通过对比之前的状态,计算出最小的dom修改步骤,再通知真实DOM做最小的修改。虚拟DOM操作最后归根结底还是作用到真实 DOM操作。

五、react受控组件和非受控组件的优化
1、什么是受控组件?
其值由React控制的输入表单元素称为“受控组件”。

2、受控组件有两个特点:
1). 设置value值,value由state控制,
2). value值一般在onChange事件中通过setState进行修改

3、什么时候使用受控组件?
需要对组件的value值进行修改时,使用受控组件。比如:页面中有一个按钮,每点击一次按钮受控组件的值加1.

4、什么是非受控组件?

表单数据由 DOM 处理的组件非受控组件。

非受控组件有两个特点:
1). 不设置value值,
2). 通过ref获取dom节点然后再取value值
6、什么时候使用非受控组件?
任何时候都不需要改变组件的value值,这时候可以使用非受控组件。

六、闭包
1、个人理解为闭包就是能够读取其它函数内部变量的函数,即一个函数内部的函数,可以说闭包是将函数内部和函数外部连接起来的一座桥梁
2、闭包用处:可以读取函数内部的变量;可以将函数内部变量的值一直保存在内存中
3、使用闭包的缺点:
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

七、document.ready和window.onload
1、在Jquery里面,我们可以看到两种写法: ( f u n c t i o n ( ) ) 和 (function(){}) 和 (function())(document).ready(function(){})
这两个方法的效果都是一样的,都是在dom文档树加载完之后执行一个函数(注意,这里面的文档树加载完不代表全部文件加载完)。
2、而window.onload是在dom文档树加载完和所有文件加载完之后执行一个函数。也就是说$(document).ready要比window.onload先执行。

八、函数表达式和函数声明及IIFE
1、 1)函数声明(Function Declaration);
// 函数声明
function funDeclaration(type){
return type===“Declaration”;
}
  
2)函数表达式(Function Expression)。
// 函数表达式
var funExpression = function(type){
return type===“Expression”;
}
Javascript 中函数声明和函数表达式是存在区别的,函数声明在JS解析时进行函数提升,因此在同一个作用域内,不管函数声明在哪里定义,该函数都可以进行调用。而函数表达式的值是在JS运行时确定,并且在表达式赋值完成后,该函数才能调用。
本质原因体现在这两种类型在Javascript function hoisting(函数提升)和运行时机(解析时/运行时)上的差异。
2、IIFE(immediately-invoked function expression)指立即执行函数,即匿名函数,ES5中本身是没有块级(私有)作用域的,但是匿名函数就有了私有作用域
IIFE写法:(function(){})();其中第一个括号是将匿名函数转为函数表达式,第二个括号是立即执行匿名函数。
IIFE的优点:1)创建块级作用域,避免向全局作用域中添加变量和函数,2)IIFE中定义的任何变量和函数都会在执行结束时被销毁,这样可以减少闭包占用的内存问题。
九、如何学习的前端?
先是在网上百度别人的学习经验以及问身边一些已经学过的人,再就是通过同学给的还不错的视频教学资源,基础打好后就是买相关的书把书都给大致看一遍。为了加深理解都是边看自己边在电脑上操作,记忆力也会加深。
带着目的和解决问题的心态,以生活中的类比来学习,就会变得有趣
前端学习大体分三个部分:html、css、javascript。首先应当用生活的类比熟悉这些概念。
比如学习html,你可以把它当做设计这房子的整体结构。头部(head),中部(body),底部(foot)就像是房子的屋顶,房间,地基。
学习css,就像是给房子做装修,墙壁刷成什么颜色,选择什么样的瓷砖装饰房间。
学习javascript,你可以把他当成是各种互动的开关控制,比如按某个按钮,可以控制电视开关换台,或者控制灯光。
十、事件模型
1、当事件触发时body会先得到有事件发生的信息,然后依次往下传递,直到到达最详细的元素。这就是事件捕获阶段。
DOM事件模型分为两种:事件冒泡和事件捕获。事件冒泡最初是微软提出的DOM事件流的模型,顾名思义,就是值浏览器的事件流如同冒泡一样,从最低处到最高处。最低处对应的是DOM中最具体的元素,最高处则是最外层元素,最外层元素一般就是document元素。
2、DOM事件处理程序的分类。DOM事件处理程序分为三种:HTML事件处理程序、DOM 0级事件处理程序、DOM 2级事件处理程序(注意:、没有DOM1级事件处理程序)。
a、HTML事件处理程序:指的是事件绑定直接写在HTML上
b、DOM 0级事件处理程序:指的是通过给JavaScript对象的事件参数属性赋值的模式,直接给btnDOM对象的onclick属性赋值的形式来绑定click事件就是DOM 0级事件处理程序,赋值可以使用匿名函数的形式,也可以使用具名函数的形式, 如需注销,只需将该属性设置为null即可
c、DOM 2级事件处理程序:指的是使用addEventListener(‘eventName’,‘eventHandle’,false),其中eventName表示事件名称、eventHandle表示事件处理函数,false表示是否启用事件捕获模式,默认为false。通过addEventListener绑定的事件只能通过removeEventListener来注销,不能使用DOM 0级中的方式注销事件处理程序。
3、DOM 0级和DOM 2级事件处理程序的主要区别:
  DOM 2级事件处理程序可以给元素的事件绑定多个处理程序。点击btn时将会依次触发clickHandle1、clickHandle2,注销事件处理程序也需要针对每个事件处理程序使用removeEventListener。DOM 0级事件处理程序如果以这种形式绑定事件,则后写的方法会覆盖掉之前的方法
4、以下事件不冒泡:blur、focus、load、unload
5、如何阻止冒泡
IE浏览器中的写法:event.cancelBubble = true;
其他标准浏览器,W3C推荐的写法:event.stopPropagation();
十一、xss攻击
1、XSS定义
XSS, 即为(Cross Site Scripting), 中文名为跨站脚本, 是发生在目标用户的浏览器层面上的,当渲染DOM树的过程成发生了不在预期内执行的JS代码时,就发生了XSS攻击。
跨站脚本的重点不在‘跨站’上,而在于‘脚本’上。大多数XSS攻击的主要方式是嵌入一段远程或者第三方域上的JS代码。实际上是在目标网站的作用域下执行了这段js代码。
2、XSS攻击方式
a) 反射型 XSS
反射型XSS,也叫非持久型XSS,是指发生请求时,XSS代码出现在请求URL中,作为参数提交到服务器,服务器解析并响应。响应结果中包含XSS代码,最后浏览器解析并执行。
从概念上可以看出,反射型XSS代码是首先出现在URL中的,然后需要服务端解析,最后需要浏览器解析之后XSS代码才能够攻击。
b) 存储型 XSS
存储型XSS,也叫持久型XSS,主要是将XSS代码发送到服务器(不管是数据库、内存还是文件系统等。),然后在下次请求页面的时候就不用带上XSS代码了。
最典型的就是留言板XSS。用户提交了一条包含XSS代码的留言到数据库。当目标用户查询留言时,那些留言的内容会从服务器解析之后加载出来。浏览器发现有XSS代码,就当做正常的HTML和JS解析执行。XSS攻击就发生了。
c) DOM XSS
DOM XSS攻击不同于反射型XSS和存储型XSS,DOM XSS代码不需要服务器端的解析响应的直接参与,而是通过浏览器端的DOM解析。这完全是客户端的事情。
DOM XSS代码的攻击发生的可能在于我们编写JS代码造成的。我们知道eval语句有一个作用是将一段字符串转换为真正的JS语句,因此在JS中使用eval是很危险的事情,容易造成XSS攻击。避免使用eval语句。
XSS攻击总结:
a) 一旦在DOM解析过程成出现不在预期内的改变(JS代码执行或样式大量变化时),就可能发生XSS攻击
b) XSS分为反射型XSS,存储型XSS和DOM XSS
c)反射型XSS是在将XSS代码放在URL中,将参数提交到服务器。服务器解析后响应,在响应结果中存在XSS代码,最终通过浏览器解析执行。
d)存储型XSS是将XSS代码存储到服务端(数据库、内存、文件系统等),在下次请求同一个页面时就不需要带上XSS代码了,而是从服务器读取。
e)DOM XSS的发生主要是在JS中使用eval造成的,所以应当避免使用eval语句。
d) XSS危害有盗取用户cookie,通过JS或CSS改变样式,Dos造成正常用户无法得到服务器响应。
f)XSS代码的预防主要通过对数据解码,再过滤掉危险标签、属性和事件等。
十二、对象
 js对象的创建一共有三种方法:对象直接量法、构造函数法、Object.create法。
 a) 对象直接量是最简单的创建方法,一个大括号里面加上用逗号分隔的名值对就搞定了.。
 b) 构造函数法就是用new关键字加上一个函数调用来返回一个对象。
 c) Object.create方法也可以创建对象,它创建出来的对象的原型就是传给Object.create方法的对象参数。如果想创建一个没有任何原型的对象,只需把null传进去:Object.create(null)
十三、继承
1、构造函数继承:

  function Parent() {
    this.name = 'parent';
}
function Child(age) {
    Parent.call(this);//使this指向Parent,继承了Parent的属性
    this.age = age;
}
var c = new Child(12);
console.log(c.name); //输出parent

缺点:无法继承Parent(父函数)原型链上的属性
2、原型链继承:

function Parent() {
    this.name = 'parent';
}
Parent.prototype.say = function () {
    console.log('say');
};
function Child(age) {
    this.age = age;
}
Child.prototype = new Parent();
var c = new Child(12);
console.log(c.name); //输出parent
c.say() //输出say

原型链继承是直接让Child构造函数的prototype直接指向Parent对象,这样的话Child可以直接从Parent的原型链上找属性
缺点:当创建多个实例时,如果不同实例可能互相存在影响
3、组合继承:

function Parent() {
    this.name = 'parent';
    this.arr = [1,2,3,4]
}
Parent.prototype.say = function () {
    console.log('say');
};
function Child(age) {
    Parent.call(this); 
    this.age = age;
}
Child.prototype = new Parent();
var c1 = new Child(12);
var c2 = new Child(12);
console.log(c1.arr); //[1,2,3,4]
console.log(c2.arr);//[1,2,3,4]
c1.arr.push(5);
console.log(c1.arr); //[1,2,3,4,5]
console.log(c2.arr); //[1,2,3,4]

优点:实例创建时就有了Parent里的属性,同时也继承了父函数原型链上的东西。这样的话寻找某些属性的时候可以先从Parent上面找,没有的话再从其原型链上找
解析:上面代码中的Child.prototype = new Parent()继承了Parent原型链的同时也继承Parent函数里面的东西。可以换成Child.prototype = Parent.prototype,就是只继承父函数原型链上的东西,但是这样的话Child的原型的constructor找到的就是Parent的constructor,原因就是因为Child.prototype = Parent.prototype这里直接将Parent的prototype直接赋值给Child的prototype,所以它的constructor肯定就是Parent的constructor,所以需要再优化,就在后面加上Child.prototype = Parent.prototype;
Child.prototype.constructor = Child;最后优化完的代码如下:

function Parent() {
    this.name = 'parent';
    this.arr = [1,2,3,4];
}
Parent.prototype.say = function () {
    console.log('say');
};
function Child(age) {
    Parent.call(this);
    this.age = age;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
var c = new Child(12);
console.log(c.name);
c.say();
console.log(c.constructor); //输出function Child(age) {Parent.call(this);this.age = age;}
console.log(new Parent().constructor); //输出Parent() {this.name = 'parent';this.arr = [1,2,3,4];}

其中用Object.create(Parent.prototype)这种方法创建一个新对象,赋值给Child.prototype,这样修改Child的constructor 时,Parent的constructor 就不会受到影响。
十四、js私有字段是什么
1、在一个函数里面重新声明一个变量或方法,就创建了私有字段,外部是无法访问到的
2、函数的外部访问:外部实例化一个对象,然后对象 . 属性或者方法就可以访问了 var p=new People() alert(p.getname())
3、JavaScript没用私有属性的概念;所有的属性都是公用的;
私有变量的概念:在任何函数中定义的变量,都是私有变量,因为不能在函数外部访问这些变量;
私有变量:包括函数的参数/局部变量和在函数内部定义的其他函数;
特权方法:内部创建一个闭包,闭包可以访问私有变量;因此创建用于访问私有变量的公用方法,称作特权方法
十五、git add 和commit的区别
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
1、git add:把要提交的所有修改放到暂存区(Stage)
2、git commit:一次性把暂存区的所有修改提交到分支(工作区)
十六、304状态码是什么
如果客户端发送了一个带条件的GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个304状态码。简单的表达就是:客户端已经执行了GET,但文件未变化。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2021前端面试真题pdf是一个面向前端开发人员的面试准备资料,里面包含了一系列与前端开发相关的问题和答案。该pdf的目的是帮助前端开发人员更好地准备和应对面试,提高面试成功的机。 该pdf的内容通常包括以下几个方面: 1. HTML、CSS和JavaScript基础知识:这些问题涉及到HTML标签的用法、CSS属性的应用和JavaScript语法等基础知识点,考察面试者对于前端基础的掌握程度。 2. 前端框架和工具:这些问题涉及到常见的前端框架,例如React、Vue等,以及前端开发常用的工具,例如Webpack和Babel等,考察面试者对于一些流行的前端框架和工具的了解和应用能力。 3. 前端性能优化和安全:这些问题涉及到前端性能优化的技巧和策略,例如减少HTTP请求、缓存、懒加载等,以及前端安全的相关知识,例如跨站脚本攻击(XSS)和跨站请求伪造(CSRF)等,考察面试者对于前端性能优化和安全的了解和实践经验。 4. 前端面试题和项目经验:该pdf中可能包含一些真实的前端面试题目,以及要求面试者提供自己在前端开发领域的项目经验和解决问题的能力,目的是评估面试者的实际应用能力和解决问题的思路。 通过研究和回答该pdf中的问题,前端开发人员可以对自己的前端知识进行系统的总结和复习,为面试做好准备。此外,该pdf还可以帮助面试者了解当前前端开发领域的热点和趋势,更好地适应行业的发展要求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值