简述盒模型?
CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距margin,边框border,填充padding,和实际内容content。盒模型允许我们在其它元素和周围元素边框之间的空间放置元素。
box-sizing:content-box(W3C盒模型,又名标准盒模型):元素的宽高大小表现为内容的大小。 box-sizing:border-box(IE盒模型,又名怪异盒模型):元素的宽高表现为内容 + 内边距 + 边框的大小。背景会延伸到边框的外沿
CSS3的新特性
word-wrap 文字换行
text-overflow 超过指定容器的边界时如何显示
text-decoration 文字渲染
text-shadow文字阴影
gradient渐变效果
transition过渡效果 transition-duration:过渡的持续时间
transform拉伸,压缩,旋转,偏移等变换
animation动画
transition和animation的区别:
Animation和transition大部分属性是相同的,他们都是随时间改变元素的属性值,他们的主要区别是transition需要触发一个事件才能改变属性,而animation不需要触发任何事件的情况下才会随时间改变属性值,并且transition为2帧,从from .... to,而animation可以一帧一帧的。
两边宽度固定中间自适应的三栏布局
圣杯布局和双飞翼布局是前端工程师需要日常掌握的重要布局方式。两者的功能相同,都是为了实现一个两侧宽度固定,中间宽度自适应的三栏布局。
圣杯布局
<style>
body{
min-width: 550px;
}
#container{
padding-left: 200px;
padding-right: 150px;
}
#container .column{
float: left;
}
#center{
width: 100%;
}
#left{
width: 200px;
margin-left: -100%;
position: relative;
right: 200px;
}
#right{
width: 150px;
margin-right: -150px;
}
</style>
<div id="container">
<div id="center" class="column">center</div>
<div id="left" class="column">left</div>
<div id="right" class="column">right</div>
</div>
双飞翼布局
<style>
body {
min-width: 500px;
}
#container {
width: 100%;
}
.column {
float: left;
}
#center {
margin-left: 200px;
margin-right: 150px;
}
#left {
width: 200px;
margin-left: -100%;
}
#right {
width: 150px;
margin-left: -150px;
}
</style>
<div id="container" class="column">
<div id="center">center</div>
</div>
<div id="left" class="column">left</div>
<div id="right" class="column">right</div>
你怎么清除浮动.
1、在浮动元素后面添加 clear:both 的空 div 元素
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div style="clear:both"></div>
</div>
2、给父元素添加 overflow:hidden 或者 auto 样式,触发BFC。
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>
.container{
width: 300px;
background-color: #aaa;
overflow:hidden;
zoom:1; /*IE6*/
}
3、使用伪元素,也是在元素末尾添加一个点并带有 clear: both 属性的元素实现的。
<div class="container clearfix">
<div class="left"></div>
<div class="right"></div>
</div>
.clearfix{
zoom: 1; /*IE6*/
}
.clearfix:after{
content: ".";
height: 0;
clear: both;
display: block;
visibility: hidden;
}
推荐使用第三种方法,不会在页面新增div,文档结构更加清晰。
浏览器渲染机制.
构建DOM树(parse):渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node
构建渲染树(construct):解析对应的CSS样式文件信息
布局渲染树(reflow/layout):从根节点递归调用,计算每一个元素的大小、位置等,给出每个节点所应该在屏幕上出现的精确坐标;
绘制渲染树(paint/repaint):遍历渲染树,使用UI后端层来绘制每个节点
重绘和回流的区别
重绘(repaint或redraw):当盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来之后,浏览器便把这些原色都按照各自的特性绘制一遍,将内容呈现在页面上。重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。
重绘发生在元素的可见的外观被改变,但并没有影响到布局的时候。比如,仅修改DOM元素的字体颜色(只有Repaint,因为不需要调整布局)
回流(重构/重排/reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建, 这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。
触发回流的条件:任何页面布局和几何属性的改变都会触发回流:
页面渲染初始化(无法避免)
添加或删除可见的DOM元素
元素位置的改变,或者使用动画
元素尺寸的改变——大小,外边距,边框
浏览器窗口尺寸的变化
填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变
回流必定会引发重绘,但重绘不一定会引发回流。
谈谈flex布局、
采用 Flex 布局的元素,称为 Flex容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex项目(flex item),简称“项目”。
1、父元素属性
属性名 | 属性值 | 备注 |
display | flex | 定义了一个flex容器,它的直接子元素会接受这个flex环境 |
flex-direction | row, row-reverse, column, column-reverse | 决定主轴的方向 |
flex-wrap | nowrap, wrap, wrap-reverse | 如果一条轴线排不下,如何换行 |
flex-flow | [flex-direction] , [flex-wrap] | 是 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 | 设置或检索弹性盒子元素在侧轴(纵轴)方向上的对齐方式 |
子元素属性 | ||
属性名 | 属性值 | 备注 |
order | [int] | 默认情况下flex order会按照书写顺训呈现, 可以通过order属性改变, 数值小的在前面,还可以是负数。 |
flex-grow | [number] | 设置或检索弹性盒的扩展比率, 根据弹性盒子元素所设置的扩展因子作为比率来分配剩余空间 |
flex-shrink | [number] | 设置或检索弹性盒的收缩比率, 根据弹性盒子元素所设置的收缩因子作为比率来收缩空间 |
flex-basis | [length], auto | 设置或检索弹性盒伸缩基准值 |
align-self | auto,flex-start,flex-end,center,baseline,stretch | 设置或检索弹性盒子元素在侧轴(纵轴)方向上的对齐方式, 可以覆盖父容器align-items的设置 |
JS作用域的理解.
JS中的作用域分为两种:全局作用域和函数作用域。函数作用域中定义的变量,只能在函数中调用,外界无法访问。没有块级作用域导致了if或for这样的逻辑语句中定义的变量可以被外界访问,因此ES6中新增了let和const命令来进行块级作用域的声明
call,apply和bind区别
三个函数的作用都是将函数绑定到上下文中,用来改变函数中this的指向;三者的不同点在于语法的不同。
fun.call(thisArg[, arg1[, arg2[, ...]]])
fun.apply(thisArg, [argsArray])
所以 apply和 call的区别是 call方法接受的是若干个参数列表,而 apply接收的是一个包含多个参数的数组。
而bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
var bindFn = fun.bind(thisArg[, arg1[, arg2[, ...]]])
bindFn()
深拷贝和浅拷贝.
浅拷贝
function simpleClone(obj) {
var result = {};
for (var i in obj) {
result[i] = obj[i];
}
return result;
}
深拷贝,遍历对象中的每一个属性
测试案例
var obj={
oName:"kky",
oAge:18,
oAddress:{
province:"beijing"
},
ofavorite:[
"swimming",
{reading:"history book"}
],
skill:function(){
console.log("bob is coding");
}
};
var arr=[1,[2,3],{user:"kky"}];
var obj2=deepClone(obj);
//深度克隆
function deepClone(obj){
var o = obj instanceof Array ? [] : {};
for(var k in obj){
o[k] = typeof obj[k] === "object" ? arguments.callee(obj[k]) : obj[k];
}
return o;
}
谈谈防抖和节流
说白了,防抖节流就是使用定时器来实现我们的目的。
防抖(debounce):
在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
典型的案例就是输入框搜索:输入结束后n秒才进行搜索请求,n秒内又输入的内容,则重新计时。
节流(throttle):
规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效。
典型的案例就是鼠标不断点击触发,规定在n秒内多次点击只生效一次。
为什么要掌握防抖和节流
函数节流(throttle)与函数防抖(debounce)都是可以限制函数的执行频次,根据不同的场景来对执行频率进行限制,避免了函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。
防抖
function debounce(fn, delay) {
let timer = null;
return function () {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
}
}
节流
function throttle(fn, cycle) {
let start = Date.now();
let now;
let timer;
return function () {
now = Date.now();
clearTimeout(timer);
if (now - start >= cycle) {
fn.apply(this, arguments);
start = now;
} else {
timer = setTimeout(() => {
fn.apply(this, arguments);
}, cycle);
}
}
}
谈谈cookie,sessionStorage和localStorage.
cookie用来保存登录信息,大小限制为4KB左右
localStorage是Html5新增的,用于本地数据存储,保存的数据没有过期时间,一般浏览器大小限制在5MB
sessionStorage接口方法和localStorage类似,但保存的数据的只会在当前会话中保存下来,页面关闭后会被清空。
数组的常用方法(至少说出8个)
改变原数组的方法
- splice() 添加/删除数组元素
语法:arrayObject.splice(index,howmany,item1,.....,itemX)
参数:
1.index:必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
2.howmany:可选。要删除的项目数量。如果设置为 0,则不会删除项目。
3.item1, ..., itemX:可选。向数组添加的新项目。
返回值: 如果有元素被删除,返回包含被删除项目的新数组。
- sort() 数组排序
语法:arrayObject.sort(sortby)
参数:
1.sortby 可选。规定排序顺序。必须是函数。。
返回值: 返回包排序后的新数组。
- pop() 删除一个数组中的最后的一个元素
语法:arrayObject.pop()
参数:无
返回值: 返回被删除的元素。
- shift() 删除数组的第一个元素
语法:arrayObject.shift()
参数:无
返回值: 返回被删除的元素。
- push() 向数组的末尾添加元素
语法:arrayObject.push(newelement1,newelement2,....,newelementX)
参数:
1.newelement1 必需。要添加到数组的第一个元素。
2.newelement2 可选。要添加到数组的第二个元素。
3.newelementX 可选。可添加若干个元素。
返回值: 返回被删除的元素。
- unshift() 向数组的开头添加一个或更多元素
语法:arrayObject.unshift(newelement1,newelement2,....,newelementX)
参数:
1.newelement1 必需。要添加到数组的第一个元素。
2.newelement2 可选。要添加到数组的第二个元素。
3.newelementX 可选。可添加若干个元素。
返回值: arrayObject 的新长度。。
- reverse() 颠倒数组中元素的顺序
语法:arrayObject.reverse()
参数:无
返回值: 颠倒后的新数组。
- copyWithin() 指定位置的成员复制到其他位置
语法:array.copyWithin(target, start = 0, end = this.length)
参数:
1.target(必需):从该位置开始替换数据。如果为负值,表示倒数。
2.start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示倒数。
3.end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
返回值: 返回当前数组。
- fill() 填充数组
语法:array.fill(value, start, end)
参数:
1.value 必需。填充的值。
2.start 可选。开始填充位置。
3.end 可选。停止填充位置 (默认为 array.length)
返回值: 返回当前数组。
不改变原数组的方法
- slice() 浅拷贝数组的元素
语法:array.slice(begin, end);
参数:
1.begin(可选): 索引数值,接受负值,从该索引处开始提取原数组中的元素,默认值为0。
2.end(可选):索引数值(不包括),接受负值,在该索引处前结束提取原数组元素,默认值为数组末尾(包括最后一个元素)。
返回值: 返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象,且原数组不会被修改。
- join() 数组转字符串
语法:array.join(str)
参数:
1.str(可选): 指定要使用的分隔符,默认使用逗号作为分隔符。
返回值: 返回生成的字符串。
- concat() 合并两个或多个数组
语法:var newArr =oldArray.concat(arrayX,arrayX,......,arrayX)
参数:
1.arrayX(必须):该参数可以是具体的值,也可以是数组对象。可以是任意多个。
返回值: 返回返回合并后的新数组。
- indexOf() 查找数组是否存在某个元素
语法:array.indexOf(searchElement,fromIndex)
参数:
1.searchElement(必须):被查找的元素
2.fromIndex(可选):开始查找的位置(不能大于等于数组的长度,返回-1),接受负值,默认值为0。
返回值: 返回下标
- lastIndexOf() 查找指定元素在数组中的最后一个位置
语法:arr.lastIndexOf(searchElement,fromIndex)
参数:
1.searchElement(必须): 被查找的元素
2.fromIndex(可选): 逆向查找开始位置,默认值数组的长度-1,即查找整个数组。
返回值: 方法返回指定元素,在数组中的最后一个的索引,如果不存在则返回 -1。(从数组后面往前查找)
- includes() 查找数组是否包含某个元素
语法:array.includes(searchElement,fromIndex=0)
参数:
1.searchElement(必须):被查找的元素
2.fromIndex(可选):默认值为0,参数表示搜索的起始位置,接受负值。正值超过数组长度,数组不会被搜索,返回false。负值绝对值超过长数组度,重置从0开始搜索。
返回值: 返回布尔
JS实现继承(至少会一种).
首先创建一个父类
// 定义一个动物类
function Animal(name, color) {
// 属性
this.name = name || 'Animal';
this.color = color || ['black'];
// 实例方法
this.sleep = function () {
console.log(this.name + '正在睡觉!');
}
}
// 原型方法
Animal.prototype.eat = function (food) {
console.log(this.name + '正在吃:' + food);
};
原型链继承
new了一个空对象,这个空对象指向Animal并且Cat.prototype指向了这个空对象,这种就是基于原型链的继承。
function Cat(name) {
this.name = name || 'tom'
}
Cat.prototype = new Animal()
var cat = new Cat()
cat.color.push('red')
cat.sleep() //tom正在睡觉!
cat.eat('fish') //tom正在吃:fish
console.log(cat.color) //["black", "red"]
console.log(cat instanceof Animal) //true
console.log(cat instanceof Cat) //true
var new_cat = new Cat()
console.log(new_cat.color) //["black", "red"]
特点:基于原型链,既是父类的实例,也是子类的实例。
缺点:1.无法实现多继承;2.所有新实例都会共享父类实例的属性。
构造继承
function Dog(name) {
Animal.call(this)
this.name = name || 'mica'
}
var dog = new Dog()
dog.color.push('blue')
dog.sleep() // mica正在睡觉!
dog.eat('bone') //Uncaught TypeError: dog.eat is not a function
console.log(dog.color) //["black", "blue"]
console.log(dog instanceof Animal) //false
console.log(dog instanceof Dog) //true
var new_dog = new Dog()
console.log(new_dog.color) //["black"]
特点:可以实现多继承(call多个),解决了所有实例共享父类实例属性的问题。
缺点:1.只能继承父类实例的属性和方法;2.不能继承原型上的属性和方法。
组合继承
function Mouse(name){
Animal.call(this)
this.name = name || 'jerry'
}
Mouse.prototype = new Animal()
Mouse.prototype.constructor = Mouse
var mouse = new Mouse()
mouse.color.push('yellow)
mouse.sleep() //jerry正在睡觉!
mouse.eat('carrot') //jerry正在吃:carrot
console.log(mouse instanceof Animal)//true
console.log(mouse instanceof Mouse)//true
var new_mouse = new Mouse()
console.log(new_mouse.color) //["black"]
特点:可以继承实例属性/方法,也可以继承原型属性/方法
缺点:调用了两次父类构造函数,生成了两份实例
HTTP与HTTPS的区别(用两句话表述
HTTP的URL由 http://起始且默认使用端口80,而HTTPS的URL由 https://起始且默认使用端口443
HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的 SSL 加密传输协议
HTTP的连接很简单,是无状态的,HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 http 协议安全