面试会问到的问题 css+js+答案

205 阅读11分钟

垂直居中

方法一、absolute+margin 实现

1、对父元素相对定位,子元素绝对定位,将top和left都设置为50%,margin上、左边距设置为本身宽度的一半

2、对父元素相对定位,子元素绝对定位,将top、left、right和bottom都设置为0,margin设置为auto

方法二、absolute+calc 实现

对父元素相对定位,子元素绝对定位,将top、left都设置为calc(50%-自身宽度一半px)

方法三、absolute+transform 实现

对父元素相对定位,子元素绝对定位,将top和left都设置为50%,transform:translate(-50%,-50%);

方法四、flex

1、给元素直接设置display:flex;  justify-content:center;  align-items:center;

2、给父元素设置display:flex;  justify-content:center;给子元素设置align-self:center;

方法五、grid

网格布局,将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局

1、  给元素设置display: grid;  justify-items: center;  align-items: center;

2、  给父元素设置display:grid;  给子元素设置justify-self:center;  align-self:center;

方法五、转行内元素

使用display:inline-block转换为行内元素,用vertical-align:middle设置垂直居中

flex

弹性布局

容器属性:

flex-direction:主轴方向(项目排列方向) 值:row左到右方向  row-reverse右到左方向 column 上到下方向column-reverse 下到上方向排列

flex-wrap:弹性元素永远沿主轴排列,如果主轴排不下,通过flex-wrap决定容器内项目是否可换行。nowrap不换行 wrap 换行第一行在上方  wrap-reverse换行,第一行在下方

flex-flow:是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap

justify-content:定义了项目在主轴上的对齐方式。flex-start(默认值):左对齐  flex-end:右对齐  center:居中  space-between:两端对齐,项目之间的间隔都相等  space-around:两个项目两侧间隔相等

align-items:定义项目在交叉轴上如何对齐。flex-start:交叉轴的起点对齐  flex-end:交叉轴的终点对齐  center:交叉轴的中点对齐  baseline: 项目的第一行文字的基线对齐  stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度

align-content:flex-start:与交叉轴的起点对齐  flex-end:与交叉轴的终点对齐  center:与交叉轴的中点对齐  space-between:与交叉轴两端对齐,轴线之间的间隔平均分布  space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍  stretch(默认值):轴线占满整个交叉轴

成员属性:

order:定义项目的排列顺序。数值越小,排列越靠前,默认为0

flex-grow:当容器宽度>元素总宽度时,设置值比例占据剩余空间。当弹性容器的宽度正好等于元素宽度总和,无多余宽度,此时无论flex-grow是什么值都不会生效

flex-shrink:定义了项目的缩小比例(容器宽度<元素总宽度时如何收缩),默认为1,即如果空间不足,该项目将缩小。如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小

如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小

在容器宽度有剩余时,flex-shrink也是不会生效的

flex-basis:元素在主轴上的初始尺寸,所谓的初始尺寸就是元素在flex-grow和flex-shrink生效前的尺寸。默认auto,当设置为0的是,会根据内容撑开。它可以设为跟width或height属性一样的值,则项目将占据固定空间

flex:flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto

align-self:允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch(如果项目未设置高度或设为auto,将占满整个容器的高度)

bfc是什么,哪些会触发

块级格式上下文

具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。

同一个元素不能同时存在于两个 BFC 中。

 

满足下列条件之一就可触发BFC:

根元素,即html

float的值不为none(默认)  为left、right

overflow的值不为visible(默认) 为hidden、scroll、auto

display的值为table-cell, table-caption, inline-block, flex, 或者 inline-flex 中的其中一个

position的值为absolute或fixed

 

BFC 的特性

BFC 是页面上的一个独立容器,容器里面的子元素不会影响外面的元素。

BFC 内部的块级盒会在垂直方向上一个接一个排列

同一 BFC 下的相邻块级元素可能发生外边距折叠,创建新的 BFC 可以避免外边距折叠

每个元素的外边距盒(margin box)的左边与包含块边框盒(border box)的左边相接触(从右向左的格式的话,则相反),即使存在浮动

浮动盒的区域不会和 BFC 重叠

计算 BFC 的高度时,浮动元素也会参与计算

 

应用:

自适应两列布局:浮动盒区域不会和bfc重叠

防止兄弟外边距(margin)重叠

防止父子元素外边距重叠 解决方法:·给父元素触发bfc(添加overflow:hidden)  ·给父元素添加border  ·给父元素添加padding

清除浮动解决父元素高度坍塌问题

 

清除浮动

浮动带来的问题:

父元素的高度无法被撑开,影响与父元素同级的元素

与浮动元素同级的非浮动元素(内联元素)会跟随其后

若非第一个元素浮动,则该元素之前的元素也需要浮动,否则会影响页面显示的结构。

 

清除浮动的方式:

父级div定义height

最后一个浮动元素后加空div标签 并添加样式clear:both。

包含浮动元素的父标签添加样式overflow为hidden或auto。

父级div定义zoom

数据类型,储存方式,

基本(值)类型

String、Number、boolean、undefined、null、symbol、bigint

基本类型是保存在栈内存中的简单数据段,它们的值都有固定的大小,保存在栈空间,通过按值访问;

 

对象(应用)类型

Object、Function、Array

引用类型是保存在堆内存中的对象,值大小不固定,栈内存中存放的该对象的访问地址指向堆内存中的对象,JavaScript不允许直接访问堆内存中的位置,因此操作对象时,实际操作对象的引用。

如何区分数组和对象

方法1 :通过 ES6 中的 Array.isArray 来识别

            console.log(Array.isArray([]))//true

console.log(Array.isArray({}))//false

方法2 :通过 instanceof 来识别

console.log([] instanceof Array)//true

console.log({} instanceof Array)//false

方法3 :通过调用 constructor 来识别

console.log([].constructor)//[Function: Array]

console.log({}.constructor)//[Function: Object]

方法4 :通过 Object.prototype.toString.call 方法来识别

console.log(Object.prototype.toString.call([]))//[object Array] 

console.log(Object.prototype.toString.call({}))//[object Object]

for of 和for in区别

for…of 是ES6新增的遍历方式,允许遍历一个含有iterator接口的数据结构(数组、对象等)并且返回各项的值,和ES3中的for…in的区别如下:

 

for…of 遍历获取的是对象的键值,for…in 获取的是对象的键名;

for… in 会遍历对象的整个原型链,性能非常差不推荐使用,而 for … of 只遍历当前对象不会遍历原型链;

对于数组的遍历,for…in 会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for…of 只返回数组的下标对应的属性值;

 

总结: for...in 循环主要是为了遍历对象而生,不适用于遍历数组;for...of 循环可以用来遍历数组、类数组对象,字符串、Set、Map 以及 Generator 对象。

增删改查

创建:

document.write

innerHTML

createElement

增:

appendChild

insertBefore

删:

removeChild

改:

主要修改dom的元素属性,dom元素的内容、属性、表单的值等

修改元素属性:src、href、title 等

修改普通元素内容:innerHTML、innerText

修改表单元素:value、type、disabled

修改元素样式:style、className

查:

主要获取查询dom的元素

DOM提供的API方法:getElementById、getElementsByTagName (古老用法,不推荐)

H5提供的新方法:querySelector、querySelectorAll (提倡)

利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling) 提倡

箭头函数和普通函数区别

ES6中允许使用箭头=>来定义箭头函数,

定义箭头函在数语法上要比普通函数简洁得多。箭头函数省去了function关键字,采用箭头=>来定义函数。函数的参数放在=>前面的括号中,函数体跟在=>后的花括号中。

 

箭头函数不会创建自己的this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this。箭头函数没有自己的this,它会捕获自己在定义时(注意,是定义时,不是调用时)所处的外层执行环境的this,并继承这个this值。所以,箭头函数中this的指向在它被定义的时候就已经确定了,之后永远不会改变。

箭头函数继承而来的this指向永远不变

箭头函数不能作为构造函数使用

箭头函数没有自己的arguments,用…arg的方法

箭头函数没有原型prototype

回流重绘,什么场景会触发

回流:布局引擎会根据各种样式计算每个盒子在页面上的大小与位置

重绘:当计算好盒模型的位置、大小及其他属性后,浏览器根据每个盒子特性进行绘制

 

回流触发时机

回流这一阶段主要是计算节点的位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流,如下面情况:

·添加或删除可见的DOM元素

·元素的位置发生变化

·元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)

·内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代

·页面一开始渲染的时候(这避免不了)

·浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)

这些属性有一个共性,就是需要通过即时计算得到。因此浏览器为了获取这些值,也会进行回流

 

重绘触发时机

触发回流一定会触发重绘

可以把页面理解为一个黑板,黑板上有一朵画好的小花。现在我们要把这朵从左边移到了右边,那我们要先确定好右边的具体位置,画好形状(回流),再画上它原有的颜色(重绘)

除此之外还有一些其他引起重绘行为:

·颜色的修改

·文本方向的修改

·阴影的修改

 

 

 

浅拷贝深拷贝,哪些触发浅拷贝,深拷贝代码实现

浅拷贝,浅拷贝是拷贝一层,如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址

在JavaScript中,存在浅拷贝的现象有:

Object.assign

Array.prototype.slice(), Array.prototype.concat()

使用拓展运算符实现的复制

 

深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址,修改一个对象的属性,不会改变另一个对象的属性

常见的深拷贝方式有:

_.cloneDeep()

jQuery.extend()

JSON.stringify()

手写循环递归


| <script>    
var obj = {      
    id: 1,      
    name: 'andy',      
    msg: {        
        age: 18     
    },      
    color: ['pink', 'red']    
};    
var o = {};     
function deepCopy(newobj, oldobj) {      
    for (var k in oldobj) {        
        var item = oldobj[k];        
        if (item instanceof Array) {          
            newobj[k] = [];          
            deepCopy(newobj[k], item)        
        } else if (item instanceof Object) {          
            newobj[k] = {};          
            deepCopy(newobj[k], item)        
        } else {          
            newobj[k] = item;        
        }      
    }    
}    
deepCopy(o, obj);    
console.log(o);    
o.msg.age = 20;    
console.log(obj); |

事件循环

事件循环机制从整体上的告诉了我们所写的JavaScript代码的执行顺序。

JavaScript的一大特点就是单线程,而这个线程中拥有唯一的一个事件循环(使用H5中的Web Workers可以多线程运行)

·执行栈:

当我们调用一个方法的时候,js会生成一个与这个方法对应的执行环境(context),又叫 执行上下文 。这个执行环境中存在着这个方法的私有作用域、上层作用域的指向、方法的参数,这个作用域中定义的变量以及这个作用域的this对象。 而当一系列方法被依次调用的时候,因为js是单线程的,同一时间只能执行一个方法,于是这些方法被排队在一个单独的地方。这个地方被称为执行栈。

当一个脚本第一次执行的时候,js引擎会解析这段代码,并将其中的同步代码按照执行顺序加入执行栈中,然后从头开始执行。如果当前执行的是一个方法,那么js会向执行栈中添加这个方法的执行环境,然后进入这个执行环境继续执行其中的代

码。 当这个执行环境中的代码 执行完毕并返回结果后,js会退出这个执行环境并把这个执行环境销毁,回到上一个方法的执行环境 。这个过程反复进行,直到执行栈中的代码全部执行完毕。

 

·事件队列:

JS引擎遇到一个异步事件后并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务,当一个异步事件返回结果后,js会将这个事件加入与当前执行栈不同的另一个队列,我们称之为 事件队列 。

被放入事件队列不会立刻执行其回调,而是 等待当前执行栈中的所有任务都执行完毕, 主线程处于闲置状态时,主线程会去查找事件队列是否有任务 。如果有,那么主线程会从中取出排在第一位的事件,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码...,如此反复,这样就形成了一个无限的循环。这就是这个过程被称为“事件循环(Event Loop)”的原因。

·宏任务(macro task)与微任务(micro task)

宏任务放至宏任务队列( 简称宏队列 )中、微任务放至微任务队列( 简称微队列 )中

宏队列 :用来保存待执行的宏任务(回调),比如: 定时器 回调/ajax回调/dom事件回调

微队列 :用来保存待执行的微任务(回调),比如: Promise 的回调/muntation回调

JS执行引擎首先必须执行所有的初始化同步任务代码

每次准备取出第一个宏任务执行前,都要将所有的微任务一个一个取出来执行

总结: 在一个事件循环中,异步事件返回结果后会被放到一个任务队列中。然而,根据这个异步事件的类型,这个事件实际上会被对应的宏任务队列或者微任务队列中去。并且在当前执行栈为空的时候,主线程会查看微任务队列是否有事件存在。如果不存在,那么再去宏任务队列中取出一个事件并把对应的回到加入当前执行栈;如果存在,则会依次执行队列中事件对应的回调,直到微任务队列为空,然后去宏任务队列中取出最前面的一个事件,把对应的回调加入当前执行栈...如此反复,进入循环。

我们只需记住: 当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行

 

 

本地存储

cookie(cookie数据大小不能超过4k 。

cookie设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。

cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端)

sessionStorage(sessionStorage 和 localStorage 使用方法基本一致,唯一不同的是生命周期,sessionStorage 数据在当前浏览器窗口关闭后自动删除;)

localStorage (localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;)

(sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存)

indexedDB

ajax

全称(Async Javascript and XML)

即异步的 JavaScript 和 XML,是一种创建交互式网页应用的网页开发技术,可以在不重新加载整个网页的情况下,与服务器交换数据,并且更新部分网页

优点:

实现局部更新(无刷新状态下),

减轻了服务器端的压力

缺点:

破坏了浏览器前进和后退机制(因为 ajax 自动更新机制)

ajax 请求多了,也会出现页面加载慢的情况。

搜索引擎的支持程度比较低。

ajax 的安全性问题不太好(可以用数据加密解决)。

 

Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用JavaScript来操作DOM而更新页面

 

XMLHttpRequest 是客户端的一个 API,它为浏览器与服务器通信提供了一个便捷通道。

通过HTTP在浏览器和web服务器之间收发XML或其它数据。XMLHTTP最大的好处在于可以动态地更新网页,它无需重新从服务器读取整个网页,也不需要安装额外的插件

 

 

es6你用到了什么新增的内容

声明变量let const(提供了块级作用域与不再具备变量提升)

变量解构赋值

展开运算符…

箭头函数

函数默认参数

Array的扩展方法:Array.form()  find()  findIndex()  includes()

模板字符串

String的扩展方法:startsWith()  endsWith()  repeat()

Set数据结构  实例方法add()  delete()  has()  clear()

遍历:s.forEach(value=>console.log(value))