html + css基础
1.基本的布局(中间自适应旁边固定啥的)的几种实现方法;
http://blog.youkuaiyun.com/kongkongyou/article/details/545617602.垂直居中的几种实现方法;
方法一、(父块子块)对父容器使用display: table-cell
+vertical-align: middle;
使其内的子元素实现垂直居中;
方法二、(父块子块)给父添加 display:flex; align-item:center;
3.盒模型;
box-sizing:box-sizing:
content-box
| border-box
| inherit
;
padding:20px;
4.position;
(1)staticstatic是position属性的默认值,默认情况下,块级元素和行内元素按照各自的特性进行显示
(2)relative
relative翻译成中文称相对定位,设置了这个属性后,元素会根据top,left,bottom,right进行偏移,关键点是它原本的空间仍然保留。
(3)absolute
元素设置成absolute后会脱离文档流,并且不占有原本的空间,后面的元素会顶替上去,而且不论元素是行内元素还是块级元素,都会生成一个块级框,也就是例如行内元素span设置了absolute后就可以设置height和width属性了。
(4)fixed
fixed的表现方式类似于absolute,但是相比于absolute相对于不确定的父元素进行偏移,fixed就是相对于浏览器窗口进行偏移。
5.行内元素和块元素;
一,下面从概念的角度来说一下块级元素和行内元素
1.块级元素,一般都是从新行开始,它可以容纳行内元素和其他块元素,常见块级元素比如div/p等。“form”这个快元素比较特殊,他只能来容纳其他块元素
2.行内元素:也叫做内联元素,一般都是语义级别的基本元素,内联元素已办只能容纳文本或者其他内联元素。
块元素(block element)和内联元素(inline element)都是html规范中的概念。块元素和内联元素的基本差异是块元素一般都是从新行开始的。而当加了css控制以后,块元素可以变为内联元素,内联元素也可以变为块元素。
3.行内元素包含替换元素和非替换元素:替换元素是浏览器根据其标签的元素与属性来判断显示具体的内容。 img、input、textarea、select、object 等都是替换元素, 可以设置宽高。大多数元素是不可替换元素,他们将内容直接告诉浏览器,将其显示出来。
这些元素都没有实际的内容二,块级元素和内联元素的区别
1.块级元素会独占一行,其宽度自动填满其父元素宽度
行内元素不会独占一行,相邻的行内元素会排列到同一行里,直到一行排不下,才会换行,其宽度随元素的内容变化而变化,
2.一般情况下,块级元素可以设置width,height属性,行内元素设置width,height无效
(注意,块级元素设置了width宽度属性后仍然是独占一行的)
3.块级元素可以设置margin,padding属性,行内元素的水平方向的padding-left和padding-right都会产生边距效果,但是竖直方向上的padding-top和padding-bottom都不会产生边距效果。
6.BFC(块级格式化上下文Block Formatting Contexts,和浮动一起考);
- 普通流 (normal flow)
在普通流中,元素按照其在 HTML 中的先后位置至上而下布局,在这个过程中,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的一个新行,除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。
- 浮动 (float)
在浮动布局中,元素首先按照普通流的位置出现,然后根据浮动的方向尽可能的向左边或右边偏移,其效果与印刷排版中的文本环绕相似。
- 绝对定位 (absolute positioning)
在绝对定位布局中,元素会整体脱离普通流,因此绝对定位元素不会对其兄弟元素造成影响,而元素具体的位置由绝对定位的坐标决定。
具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。相当于普通流。
通俗一点来讲,可以把 BFC 理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。
只要元素满足下面任一条件即可触发 BFC 特性:
- body 根元素
- 浮动元素:float 除 none 以外的值
- 绝对定位元素:position (absolute、fixed)
- display 为 inline-block、table-cells、flex
- overflow 除了 visible 以外的值 (hidden、auto、scroll)
BFC 特性及应用:
1. 同一个 BFC 下外边距会发生折叠3. BFC 可以阻止元素被浮动元素覆盖
一般通过overflow:hidden触发BFC解决上面的问题7.animation;
8.伪元素伪类;
伪元素是对元素中的特定内容进行操作,它所操作的层次比伪类更深了一层,也因此它的动态性比伪类要低得多。实际上,设计伪元素的目的就是去选取诸如元素内容第一个字(母)、第一行,选取某些内容前面或后面这种普通的选择器无法完成的工作。它控制的内容实际上和元素是相同的,但是它本身只是基于元素的抽象,并不存在于文档中,所以叫伪元素。
:first-letter :first-line :before :after :
伪类选择元素基于的是当前元素处于的状态,或者说元素当前所具有的特性,而不是元素的id、class、属性等静态的标志。由于状态是动态变化的,所以一个元素达到一个特定状态时,它可能得到一个伪类的样式;当状态改变时,它又会失去这个样式。由此可以看出,它的功能和class有些类似,但它是基于文档之外的抽象,所以叫伪类。
a:link {color:#FF0000;} /* 未访问的链接 */
a:visited {color:#00FF00;} /* 已访问的链接 */
a:hover {color:#FF00FF;} /* 鼠标划过链接 */
a:active {color:#0000FF;} /* 已选中的链接 */
:first-child :last-child :nth-child(n)
9.less、sass、stylus这种预处理器;
https://www.w3cplus.com/css/css-preprocessor-sass-vs-less-stylus-2.htmlCSS预处理器用一种专门的编程语言,进行Web页面样式设计,然后再编译成正常的CSS文件,以供项目使用。
Sass是对CSS(层叠样式表)的语法的一种扩充,诞生于2007年,最早也是最成熟的一款CSS预处理器语言,它可以使用变量、常量、嵌套、混入、函数等功能,可以更有效有弹性的写出CSS。Sass最后还是会编译出合法的CSS让浏览器使用,也就是说它本身的语法并不太容易让浏览器识别,因为它不是标准的CSS格式,在它的语法内部可以使用动态变量等,所以它更像一种极简单的动态语言.
Less是2009年开源的一个项目,受Sass的影响较大,但又使用CSS的语法,让大部分开发者和设计师更容易上手。LESS提供了多种方式能平滑的将写好的代码转化成标准的CSS代码,在很多流行的框架和工具中已经能经常看到LESS的身影了(例如Twitter的Bootstrap框架就使用了LESS)。
Stylus,2010年产生,来自于Node.js社区,主要用来给Node项目进行CSS预处理支持,在此社区之内有一定支持者,在广泛的意义上人气还完全不如Sass和LESS。
js基础
深入理解js系列1.原型链;
- 原型是一个对象,其他对象可以通过它实现属性继承。任何一个对象都可以成为继承,所有对象在默认的情况下都有一个原型,因为原型本身也是对象,所以每个原型自身又有一个原型。任何一个对象都有一个prototype的属性,记为:__proto__。每当我们定义一个对象,其__proto__属性就指向了其prototype。示例如下:
- var foo = {
- x: 10,
- y: 20
- };
- 原型对象链=原型对象继承
对象的原型指向对象的父,而父的原型又指向父的父,这种原型层层的关系,叫做原型链。
在查找一个对象的属性时,javascript会向上遍历原型链,直到找到给定名称的属性为止,当查找到达原型链的顶部,也即是Object.prototype,仍然没有找到指定的属性,就会返回undefined。
2.闭包;
指有权访问另一个函数作用域的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另外一个函数,并返回。
1. 希望一个变量长期驻扎在内存中
2. 避免全局变量的污染
3. 私有成员的存在
我们刚才说到过,闭包可以读取到函数内部的变量,这是由于闭包后函数的堆栈不会释放,也就是说这些值始终保持在内存中。这是一个优点,也是一个缺点。
我们可以通过闭包来实现一个计数器,而不用担心全局变量的污染:
function f1(){
var n=999;
nAdd=function(){n+=1}//全局变量
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
可以看到n一直存储在内存中,并没有在f1调用后被自动清除。
我们再来看看如何通过闭包来模拟javascript中的私有成员:模块化开发
var aaa = (function(){
var a = 1;
function bbb(){
a++;
alert(a);
}
function ccc(){
a++;
alert(a);
}
return {
b:bbb, //json结构
c:ccc
}
})();
aaa.b(); //2
aaa.c() //3
3.类和继承(es5实现方法 + es6实现方法);
- ES5创建类:
‘use strict’;
function Person(name){
this.name = name;
}
Person.prototype.sayName = function(){
return this.name;
}
- ES6创建类:
class Person{ constructor(name){ this.name = name; } sayName(){ return this.name; } }
4.let、const、var;
- var: 函数作用域,变量提升
- let:块级作用域,let的特点是不会变量提升,而是被锁在当前块中。
临时死区的意思是在当前作用域的块内,在声明变量前的区域叫做临时死区。
- const: 块级作用域,声明常量,一旦声明,不可更改,而且常量必须初始化赋值。
声明常量,一旦声明,不可更改,而且常量必须初始化赋值。我们试试重新声明type,看看会报什么错:const虽然是常量,不允许修改默认赋值,但如果定义的是对象Object,那么可以修改对象内部的属性值。
5.promise;
6.异步处理方法;
7.写一个方法遍历所有文档树所有节点(考察递归);
8.cookie和webstorege;
9.jsonp和跨域;
10.sort排序相关(注意ascll这个坑)
11.数组和对象的深浅拷贝;
- 浅拷贝就是流于表面的拷贝方式;当属性值为对象类型时,只拷贝了对象数据的引用,导致新旧数据没有完全分离,还会互相影响。array.concat()或者array.slice() 是特殊的实现数组浅拷贝的方式。
- 实现对象浅拷贝
function mixin(sourceObj,targetObj){ for(var key in sourceObj){ if(!(key in targetObj){ targetObj[key] = sourceObj[key]; } } return targetObj; }
- 深拷贝就是 ‘完全'拷贝,拷贝之后新旧数据完全分离,不再共用对象类型的属性值,不会互相影响。
- 一定要理解造成浅拷贝的原因:对象类型数据复制时,复制了引用地址,用的还是同一个数据对象;所以实现深拷贝的方式就是要对 对象类型属性值递归进行深拷贝,避免直接赋值。
取巧方式 JSON.parse(JSON.stringify(Obj))
12345var
test = [1,
'a'
,{name:
'lei'
,age:18}];
var
copy1 = JSON.parse(JSON.stringify(test));
//特殊方式
console.log(copy1);
copy1[2].name =
'zhang'
console.log(test);
//[1,'a',{name:'lei',age:18}] 未受到影响
注意:这种方式不能深拷贝有属性值为函数的对象, 可自行尝试
//实现深拷贝 function deepCopy( target ){ if(typeof target !== 'object') return ; //判断目标类型,来创建返回值 var newObj = target instanceof Array ? [] : {}; for(var item in target){ //只复制元素自身的属性,不复制原型链上的 if(target.hasOwnProperty(item)){ newObj[item] = (typeof target[item] == 'object') ? deepCopy(target[item]) : target[item] //判断属性值类型 } } return newObj }
12.String + Array的一些基本操作;
13.写一个数组去重的方法;
let arr = [1,1,2,2,3,3];
let s = new Set(arr);
let newArr = Array.from(s);
[...new Set([1,2,3,1,'a',1,'a'])]
14.冒泡和捕获;
15.事件代理;
16.this相关(注意箭头函数的this指向问题);
当一个函数作为对象的方法被调用时,默认this的值等于那个对象。
function sayName(){
console.log(this.name)
}
var p1 = {
name:'n',
sayName:sayName
}
var p2 = {
name:'m',
sayName:sayName
}
var name = 'sophia';
p1.sayName();//n
p2.sayName();//m
sayName();//sophia
深入理解ES6箭头函数的this以及各类this面试题总结
window.val = 1;
var obj = {
val: 2,
dbl: function () {
this.val *= 2;
val *= 2;
console.log(val);
console.log(this.val);
}
};
// 说出下面的输出结果
obj.dbl();
var func = obj.dbl;
func();
结果是: 2 4 8 8
17.call、apply、bind;
JavaScript中,一切皆对象,函数是对象,对象可以有方法,所以函数也有方法。1. call()方法:第一个参数指定了函数执行时this的值,其后的所有参数都是需要被传入函数的参数
function sayName(label){
console.log(label+“:”+this.name)
}
var p1 = {
name:'n'
}
var p2 = {
name:'m'
}
var name = 'sophia';
sayName.call(this,'global'); //global:sophia
sayName.call(p1,'p1'); //p1:p1
sayName.call(p2,'p2'); //p2:p2
2.apply()方法:第一个参数指定了函数执行时this的值,第二个参数是数组内含需要被传入函数的参数(eg:arguments)
function sayName(label){
console.log(label+“:”+this.name)
}
var p1 = {
name:'n'
}
var p2 = {
name:'m'
}
var sp1 = sayName.bind(p1);
sp1("p1");
var sp2 = sayName.bind(p2);
sp2("p2");
p2.sayName = sp1;
p2.sayName("p2");
18.变量提升;
19.高阶函数;
20.动画;
21.setTimeout、setInterval和requestAnimationFrame;
22.模块化开发;
点击打开链接
23.引起内存泄漏的原因;
javascript中的变量分为两种,原始值和引用值。原始值指的是原始数据类型的值,比如undefined,null,number,string,boolean类型所表示的值。引用值指的是复合数据类型的值,即Object,Function,Array等。
原始值和引用值存储在内存中的位置分别为栈和堆。原始值是存储在栈中的简单数据段,他们的值直接存储在变量访问的位置。引用值是存储在堆中的对象。
存储在栈中的值是一个指针,指向存储在堆中的实际对象。
我们来看一段代码:
- function Person(id,name,age){
- this.id = id;
- this.name = name;
- this.age = age;
- }
- var num = 10;
- var bol = true;
- var str = "abc";
- var obj = new Object();
- var arr = ['a','b','c'];
- var person = new Person(100,"jxl",22);
再看看内存分析图:
由上图可知我们无法直接操作存储在堆中的数据,但是我们可以通过栈中的引用来操作对象。那么为什么要分开呢?不都是存储在内存中吗?
栈的优势就是存取速度比堆要快,仅次于直接位于CPU中的寄存器,但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,垃圾收集器会自动地收走这些不再使用的数据,但是缺点是由于在运行时动态分配内存,所以存取速度较慢。
所以相对于简单数据类型而言,他们占用内存比较小,如果放在堆中,查找会浪费很多时间,而把堆中的数据放入栈中也会影响栈的效率。比如对象和数组是可以无限拓展的,正好放在可以动态分配大小的堆中。
- 全局变量引起的内存泄漏
function leaks(){ leak = 'xxxxxx';//leak 成为一个全局变量,不会被回收 }
- 闭包引起的内存泄漏
var leaks = (function(){ var leak = 'xxxxxx';// 被闭包所引用,不会被回收 return function(){ console.log(leak); } })()
- dom清空或删除时,事件未清除导致的内存泄漏
<div id="container">
</div>
$('#container').bind('click', function(){ console.log('click'); }).remove(); // zepto 和原生 js下,#container dom 元素,还在内存里jquery 的 empty和 remove会帮助开发者避免这个问题
<div id="container">
</div>
$('#container').bind('click', function(){ console.log('click'); }).off('click').remove(); //把事件清除了,即可从内存中移除
关于这个问题,更详细的内容可以参考我的另外一篇文章关于 dom清空的内存泄漏问题
- 子元素存在引用引起的内存泄漏
- 黄色是指直接被 js变量所引用,在内存里
- 红色是指间接被 js变量所引用,如上图,refB 被 refA 间接引用,导致即使 refB 变量被清空,也是不会被回收的
- 子元素 refB 由于 parentNode 的间接引用,只要它不被删除,它所有的父元素(图中红色部分)都不会被删除
$.ajax({
async: true,
type: "POST",
url: domainName + "/institution/mine",
dataType: "json",
data: {
token_key: IL.token_key,
},
success: function (data) {
}
25.map、filter、reduce相关;
26.Map和Set;
27.移动端开发相关;
28.从浏览器打开到页面渲染完成,花费了多少时间
是的,这个问题有点熟悉,面试官比较常问的是从浏览器打开到页面渲染完成,发生了什么事情。这个问题网上很多回答,我也不就重复的细说了。主要的过程是:
浏览器解析->查询缓存->dns查询->建立链接->服务器处理请求->服务器发送响应->客户端收到页面->解析HTML->构建渲染树->开始显示内容(白屏时间)->首屏内容加载完成(首屏时间)->用户可交互(DOMContentLoaded)->加载完成(load)
框架和工具相关
1.单页面应用是什么
单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。对于SPA ( single page application 单页面应用),尤其是做移动端的网页应用,由于使用 <a/> 标签实现页面的切换和跳转,会有一定的加载时间消耗。
将网页应用做成一个SPA单页面应用,用视图切换(隐藏和显示)来模拟页面的切换。而但你的项目使用了vue进行开发,那么在实现视图切换的时候,你就可以借助vue-router来帮助你方便地实现视图切换。
2.vue数据绑定原理;
数据劫持,就是通过Object.defineProperty()来劫持对象属性的setter和getter操作,在数据变动时做你想要做的事情
通过 Object.defineProperty
实现的
<body>
<div id="app">
<input type="text" id="txt">
<p id="show-txt"></p>
</div>
<script>
var obj = {}
Object.defineProperty(obj, 'txt', {
get: function () {
return obj
},
set: function (newValue) {
document.getElementById('txt').value = newValue
document.getElementById('show-txt').innerHTML = newValue
}
})
document.addEventListener('keyup', function (e) {//订阅者模式
obj.txt = e.target.value
})
</script>
</body>
3.vue父子组件和兄弟组件的通信问题;
- 父组件→子组件:props是单向绑定的(父→子),是vue为了防止子组件无意修改了父组件的数据和状态,如果多个子组件任意地对父组件进行修改,这会让这很整个应用的数据流难以阅读。如果你想修改父组件传过来的数据,最好是定义一个局部的变量,来依赖传过来的数据。
- 子组件→父组件:自定义事件。
<div id="app">
<son @connect="say"></son>
</div>
Vue.component('son',{
template:`<button @click="send">
点击
</button>`,
data(){//data必须是个函数
return{
msg:'大家好,我是子组件的数据'
}
},
methods:{
send(){
this.$emit('connect',this.msg);
}
});
const app = new Vue({
el:"#app",
methods:{
say(msg){
console.log(msg);
}
}
});
- 非父子组件通信:除了父子组件的相互通信,非父子关系的组件该如何通信,我们可以巧妙地利用一个空的vue实例来作为一个中央事件总线。
4.vuex的原理;
uex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态
。这里的关键在于集中式存储管理
。这意味着本来需要共享状态的更新是需要组件之间通讯的,而现在有了vuex,就组件就都和store通讯了。问题就自然解决了。
这就是为什么官网再次会提到Vuex构建大型应用的价值。如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex
。
5.vuex的action和mutation的异步操作和同步操作问题;
6.vue的事件监听;
7.vue-router获取自定义参数;
8.vue-router的go相关;
9.vue组件设计相关;
10.模块化的工具;
11.webpack打包优化;
12.设计一个自己的打包工具需要设计哪些主要功能;
13.babel相关;
14.mvvm的好处;
15.jquery的一些基本用法;
16.lodash相关;
17.vue和react的对比;
18.vue和jquery的对比;......