1. 三列布局知识:
(1)圣杯布局:
圣杯布局使用float、负margin和relative,不需要添加额外标签。.main元素设置padding,为两侧定宽元素留出位置。内容元素设置100%宽度,占据中间位置。而两侧定宽元素通过设置负margin和relative的偏移属性配合,到达相应位置。(缺点: 并没有实现等高布局;使用了相对定位,扩展性不好)
(2)双飞翼布局:
双飞翼布局在圣杯布局的基础上,通过为.main元素外添加一层div结构,不使用相对定位。在.main元素上设置margin。两侧的定宽列通过负margin来占据.main元素的margin区域。(缺点: 并没有实现等高布局,增加了html结构)
总结:由于限定了主要内容元素在html结构中位于前面,通过css样式改变将其位置调换到中间的前提,所以思路并不是很多。float浮动流的元素可以通过负margin调换位置;absolute绝对定位流的元素可以通过偏移属性调换位置;flex弹性盒模型可以通过order属性调换位置;grid通过grid-area调换位置。而处于正常流中的元素除了使用relative外,使用负margin是无法调换位置的,所以table、inline-block等布局方式在此前提下不是很实用。
2. margin折叠问题
外边距折叠,指的是毗邻的两个看或多个外边距 (margin) 在垂直方向会合并成一个外边距。
触发条件:毗邻,没有被非空内容、padding、border 或 clear 分隔开的margin特性. 非空内容就是说这元素之间要么是兄弟关系或者父子关系。这些 margin 都处于普通流中,即非浮动元素,非定位元素
html:
<div class="outer">
<div class="inner">Content</div>
</div>
css:
.outer {
b margin-top: 100px;
}
.inner {
margin-top: 50px;
}
比邻元素的边距总是折叠。但是得除了以下几种情况:
- 根元素不折叠
- 有间隙不折叠
- 浮动不折叠
- 创建BFC与子不折叠
- positioned 不折叠
- inline-box 不折叠
- 兄弟有间隙不折叠
- 父子间有padding 和 border 不折叠
3. 手动实现debounce throttle reduce函数(跟闭包相关知识)
- 什么是闭包:
Closures(闭包)是使用被作用域封闭的变量,函数,闭包等执行的一个函数的作用域。通常我们用和其相应的函数来指代这些作用域。(可以访问独立数据的函数)。闭包是一个函数和声明该函数的词法环境的组合。从理论角度来说,所有函数都是闭包。
- debounce函数:也就是防抖函数,调用动作在一定时间后才执行操作,若这段时间内再次调用动作,则重新计算执行时间。好比手一直按着弹簧,直至手松开后才执行操作。
$('#input').on('input', debounce(inputChange, 300));
function debounce (fn, ms){
var timer;
return function(){
let that =this;
timer &&clearTimeout(timer);
timer =setTimeout(()=>{
console.log(this);
fn.call(this, 'aa','bb');
}, ms);
}
}
function inputChange(){
let c =$(this).val();
console.log(arguments[0],arguments[1])
}
- throttle函数:也就是节流函数,调用动作的时刻大于等于执行周期,则执行该动作,然后进入下一新周期。好比水龙头的水在不断流出,节流函数控制水龙头开关,使水以水滴形式让水流出。
function throttle(fn, ms){
let timer;
return function(){
if(timer){
return
}else{
fn.call(this);
timer =setTimeout(()=>{
clearTimeout(timer)
timer =null;
},times);
}
}
}
arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。
- educe函数:
function meduce(arr, fn){
var result;
if(arr && arr.length >0){
for(let i =0; i < arr.length; i++ ){
if(i ==0){
result = arr[i]
}else{
result = fn.call(this, result,arr[i])
}
}
}
return result
}
function add(x,y){
return x*y
}
let c =meduce(a, add);
(代码自己简单实现,不一定全面,仅供参考)
4. 箭头函数的this指向问题,手动实现call, apply, bind函数
普通函数中的this:
1. this总是代表它的直接调用者(js的this是执行上下文), 例如 obj.func ,那么func中的this就是obj。
2. 在默认情况(非严格模式下,未使用 'usestrict'),没找到直接调用者,则this指的是 window (约定俗成)。
3. 在严格模式下,没有直接调用者的函数中的this是undefined。
4. 使用call,apply,bind(ES5新增)绑定的,this指的是 绑定的对象。
箭头函数中的this:箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),而不是执行时的对象, 定义它的时候,可能环境是window; 箭头函数可以方便地让我们在 setTimeout ,setInterval中方便的使用this。
call、apply、bind实现如下:
Function.prototype.myCall=function(obj, ...arg){
obj.newFn =this;
obj.newFn(...arg);
delete obj.newFn;
}
Function.prototype.myApply=function(obj, arr){
let args = [];
for(let i=0; i<arr.length;i++){
args.push(arr[i]);
}
returnthis.myCall(obj, ...args);
}
Funtion.prototype.myBind=function(obj, ...arg1){
return (...arg2)=>{
let args = arg1.concat(arg2);
let val;
obj._fn_ =this;
val = obj._fn_(...args);
delete obj._fn_;
return val
}
}
5. css里的百分比都是以谁为基数的?如何实现一个随窗口大小变化的正方形?
百分比:
- 相对于父元素宽度的:[max/min-]width、left、right、text-indent、padding、margin 等;
- 相对于父元素高度的:[max/min-]height、top、bottom 等;
- 相对于主轴长度的:flex-basis 等;相对于继承字号的:font-size 等;
- 相对于自身字号的:line-height 等;
- 相对于自身宽高的:border-radius、background-size、border-image-width、transform: translate()、transform-origin、zoom、clip-path 等;
- 相对于行高的:vertical-align 等;
- 特殊算法的:background-position (方向长度 / 该方向除背景图之外部分总长度)、border-image-slice (相对于图片尺寸)、filter 系列函数等;
实现随窗口大小变化的矩形:
- 以宽度为基准——width: 20%; padding-bottom: 20%; (两个%不等即为矩形,相等为正方形)
- 以高度为基准——同理
6. rem的font-size写在body里可不可以?
不可以。当使用 rem 单位,他们转化为像素大小取决于页根元素的字体大小,即 html 元素的字体大小。根元素字体大小乘以你 rem 值。
7. []==false {}==false结果是什么 == 的运行机制是什么?
[]==false结果是true,{}==false的结果是报错(Uncaught SyntaxError: Unexpected token ==)。
1. 是否有NaN
首先判断双等号两边是否有NaN,如果有的话,则一律返回false。
2. 是否有boolean值
如果有的话则将true转化为1,false转化为0。
3. null和undefined
遇到null或者undefined,则不会进行类型转换,它们相互的比较都返回true。
4. 有一边是字符串
分四种情况:
1)同样是字符串,则直接进行字符串值的比较
2)是数字,则需要将字符串转化为数字,然后进行比较
3)有布尔类型,则要将布尔类型转化为0或则1,然后进行比较
4)对象或者数组类型,则需要调用toString()或者valueOf()方法转化成简单类型,然后进行比较
对象转化为简单类型时会优先调用valueOf方法,如果可以与简单值进行比较则会直接比较,此时不再调用toString方法。如果调用valueOf方法后无法与简单值进行比较,则会再调用toString方法,最终得到比对的结果。但是需要注意的一点是Date对象不满足上述的规则,Date对象的toString和valueOf方法都是重新定义过的,默认会调用toString方法。
8. Event Loops :
task主要包含:setTimeout
、setInterval
、setImmediate
、I/O
、UI
交互事件
microtask主要包含:Promise
、process.nextTick
、MutaionObserver
- queue可以看做一种数据结构,用以存储需要执行的函数
- timer类型的API(setTimeout/setInterval)注册的函数,等到期后进入task队列(这里不详细展开timer的运行机制)
- 其余API注册函数直接进入自身对应的task/microtask队列
- Event Loop执行一次,从task队列中拉出一个task执行
- Event Loop继续检查microtask队列是否为空,依次执行直至清空队列
输出打印结果是多少:
console.log(1)
setTimeout(() => {
console.log(2)
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(5)
})
process.nextTick(() => {
console.log(3)
})
})
new Promise(resolve => {
console.log(7)
resolve()
}).then(() => {
console.log(8)
})
process.nextTick(() => {
console.log(6)
})
@ 1,7,6,8,2,4,3,5
9. http和websocket之间的关系是什么?注意是关系不是不同
相同点:
1. 都是基于TCP协议基础上,HTTP如此,websocket亦如此
2. 都是需要经过request,response阶段,其中websocket在发起请求的时候其实相当于借用了http的头部格式,区别就在于websocket请求头部有一个upgrade:websocket这样的字段(当然还有其他字段,但是这个字段最为关键)。
3. 如果请求失败,返回的错误编号都是相同的,例如:4**等
再说不同点:
1. 正如前面所说,websocket的请求的头部会跟http请求头部有区别,比如多了一个upgrade:websocket字段。
2. websocket只能是直连,不能通过代理来转发。究其原因应该怕如果通过代理转发的话,一个代理要承受如此多的websocket连接不释放,类似于一次DDOS攻击了。
3. websocket传输的数据是二进制流,是以帧为单位的,http传输的是明文传输,是字符串传输。
4. websocket是全双工通信,有点类似于socket通信,在建立连接之后不必再像http那样你一个request我才回一个response了,想发就发,收发自如。
10. ajax的get和post有什么不同
(1)get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTPpost机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。
(2)对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。两种方式的参数都可以用Request来获得。
(3)get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,因服务器的不同而异。
(4)get安全性非常低,post安全性较高。
(5)<formmethod="get" action="a.asp?b=b">跟<form method="get" action="a.asp">是一样的,也就是说,method为get时action页面后边带的参数列表会被忽视;而<form method="post" action="a.asp?b=b">跟<form method="post" action="a.asp">是不一样的。
11. 如何用一个div实现滴滴的logo 提示 下面的不是纯半圆 是椭圆
.box{
margin: 50px;
width: 100px;
height: 100px;
background-color: #fff;
border-radius: 20px;
text-align: center;
border: 1pxsolid#eee;
position: relative;
box-shadow: 3px3px10px#555;
}
.didi{
width: 60px;
height: 50px;
background: #fff;
border-radius: 0%0%50%50%;
border: 10pxsolid;
border-color: #ff6600;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
box-sizing: border-box;
}
.didi:before{
content: '';
width: 10px;
height: 10px;
background: #fff;
position: absolute;
right: -10px;
top: -10px;
}
12. 从输入URL到页面加载完成的过程中都发生了什么事情?
(1)输入地址
(2)浏览器查找域名的 IP 地址
(3)这一步包括 DNS 具体的查找过程,包括:浏览器缓存->系统缓存->路由器缓存...
(4)浏览器向 web 服务器发送一个 HTTP 请求
(5)服务器的永久重定向响应(从 http://example.com 到 http://www.example.com)
(6)浏览器跟踪重定向地址
(7)服务器处理请求
(8)服务器返回一个 HTTP 响应
(9)浏览器显示 HTML
(10)浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)
(11)浏览器发送异步请求
13. 如何优化网页的加载速度?
1.优化图片资源的格式和大小:
一个网页中,图片资源的大小占比是最多的,而且单个的文件的大小也很可观。因此,在保证图片质量不变的情况下,尽可能的使用高压缩率的图片格式,图片格式可以按照这个优先级选择webp > jpeg > png > bmp。同时也要根据图片展示尺寸来拉取大小最为匹配的图片资源,不要没事就把原图拉下来使用。以前我就遇到过这种情况,一个196*196大小区域展示的图片,它的文件竟然达到了几兆,最后才发现把1960*1960分辨率的原图拉下来了。
2.开启网络压缩:
大部分浏览器在发出请求时,会带上这个标记「Accept-Encoding:gzip, deflate」,表示这个浏览器可以接受以gzip压缩方式传输数据,如果你的网页服务器也支持gzip压缩数据,那么数据以gzip方式传输时,会减少70~80%的流量。
3.使用浏览器缓存:
同一个站点下面的不同页面,往往都会复用一部分资源文件,如果把这些资源文件设置为可缓存的,那么在刷新或者跳转到另一个页面时,都无须再从网络拉取相关资源,这样就大大加快了网页的加载速度。
4.减少重定向请求:
有的网站对于不同的终端制作了不同的页面,比如说在手机上访问微博,会从weibo.com重定向至weibo.cn,每一次重定向都会导致浏览器重新发起请求,延长加载时间。对于这种情况,应该尽可能使用响应式设计,一个weibo.com站点覆盖至所有终端。
5.使用CDN存储静态资源:
CDN是一种静态内容分发网络,它在每个省,甚至每个城市都部署有自己的服务器,用于分发这些静态内容,那么当某个城市的用户要拉取某个资源时,他会首选从本地的CDN服务器上拉取,这样可以保证他最快速的获得该资源。据砖家统计,网络资源中有70%的是静态资源。这就意味着,有70%的内容产生后是不会变化,那么将它们全部放在CDN上面,可以提升这70%的资源的下载速度。
6.减少DNS查询次数:
很多人喜欢把不同的图片挂在不同当域名下,比如说图片A挂在a.pm-teacher.com,图片B挂在b.pm-teacher.com。当一个网页同时使用图片A和图片B时,浏览器需要查询两个域名,要知道,每次解析域名都是会浪费时间的,所以尽可能的将全部图片放在一个域名下。
7.压缩css和js内容:
这里说的压缩和第2点并不重复,上面提到的压缩是不改变文件内容的压缩。而css和js中有大量的空格和变量命名(如hello="helloword";),如果将这些空格去除,并用简单的字母来代换变量名(如a="helloword";),那么这些css和js原文件的大小也会缩小,这样也对加快拉取速度是有帮助的。
不知道你有没有看出来,上面提到的优化方案的核心就3点:减少请求数、减少资源大小、找最快的服务器,如果你是一个网站的产品经理,快去找你们的开发确认是否有做过类似的优化吧。
14. CSS3实现0.5px的边框
方法一:利用渐变
关于渐变可以看下面两篇文章做深入了解:
实现原理:
把元素的伪类高度设为1px,背景渐变,一半有颜色,一半透明。
.container{
width: 500px;
margin: 0px auto;
}
.border-gradient{
position:relative;
padding: 10px;
}
.border-gradient:after {
content: " ";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
background-image: linear-gradient(0deg, #f00 50%, transparent 50%);
}
方法二:利用缩放
原理:transform:scale()来达到压缩一半的目的。
.container{
width: 500px;
margin: 0px auto;
}
.border-scale{
position:relative;
padding: 10px;
}
.border-scale:after{
content: " ";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
background-color: #f00;
/*如果不用 background-color, 使用border-top:1px solid #f00; 效果是一样的*/
-webkit-transform: scaleY(.5);
transform:scaleY(.5);
}
15. 原型,构造函数
结果输出多?
Object.prototype.a ='zhaolandelong';
Function.prototype.b ='chenjianming';
functionmyfun(){} var p =newmyfun();
console.log(p.a);
console.log(p.b);
console.log(myfun.b);
//zhaolandelong undefined chenjianming
16. bootstrap 实现的 clearfix
.clearfix {
*zoom: 1;
}
.clearfix:before,
.clearfix:after {
display: table;
line-height: 0;
content: "";
}
.clearfix:after {
clear: both;
}
小知识:
1、json转对象的方法:
举例:
var str = '{"name":"小明","age":18}';
将字符串转化json对象:
1. var json = JSON.parse(str);
2. var json = eval("(" + str + ")");
3. var json = (new Function("return " + str))();