前端基础

JavaScript

闭包

闭包 就是有权访问另一个函数作用域中的变量的函数。

两个作用:一是封装私有变量(通过闭包读取函数内部的变量),二是延长变量的寿命(让这些变量的值始终存在于内存中)。

作用域

每个函数都有自己的执行环境(关联一个变量对象),执行环境定义了变量或函数有权访问的其他数据。

当执行流进入一个函数时,函数的环境会被推入一个环境栈中,在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。

任何执行上下文时刻的作用域,都是由作用域链来实现。

代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链保证对执行环境有权访问的所有变量和函数的有序访问。

this

this 永远指向函数运行时所在的对象(全局环境下指向 window),而不是函数被创建时所在的对象。匿名函数或不处于任何对象中的函数(内部函数)指向 window 。

1
2
3
4
5
6
7
8
9
10
11
12
13
'use strict';
var obj = {
text: 'hello world',
foo: function(){
// fix: var that = this;
return function(){
// fix: console.log(that.text);
console.log(this.text);
}()
}
}
obj.foo();
// Uncaught TypeError: Cannot read property 'text' of undefined

修复办法是,把外部作用域中的 this 对象保存在一个闭包能够访问到的变量里,就可以通过闭包访问该对象了。

继承

a. 组合继承(原型链 + 构造函数)

使用原型链实现对原型属性和方法的继承,使用构造函数实现对实例属性的继承。将父类的新实例赋值给构造函数的原型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Parent(name){
this.name = name;
}
Parent.prototype.sayHi = function(){
alert('hi ' + this.name);
}

function Child(name, age){
Parent.call(this, name);
this.age = age;
}

Child.prototype = new Parent;
Child.prototype.constructor = Child;

var child = new Child('Tom', 15);
child.sayHi();

b. 原型式继承

先创建一个临时性构造函数,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型数的一个新实例。

1
2
3
4
5
function extends(parent){
var F = new function(){};
F.prototype = parent;
return new F();
}

也可以使用 ES5 的 Object.create() 实现原型式继承。

1
2
3
4
var parent = {
name: 'Tom'
};
var child = Object.create(parent);

事件

事件流:分两种,IE的是 事件冒泡流 ,事件开始时从最具体的元素接收,逐级向上传播到较为不具体的节点(Element -> Document)。与之相反的是 Netscape 的 事件捕获流

DOM2级事件规定事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。

大多数情况下都是将事件处理程序添加到事件流的冒泡阶段。一个 EventUtil 的栗子:

1
2
3
4
5
6
7
8
9
10
11
12
var EventUtil = {
addHandler: function(element, type, handler){
if(element.addEventListener){
element.addEventListener(type, handler, false);
}else if(element.attachEvent){
element.attachEvent('on' + type, handler); // IE8
}else{
element['on' + type] = handler;
}
},
removeHandler: function(){...}
}

事件委托:利用事件冒泡,只指定一个处理程序来管理某一类型的所有事件。是一种对“事件处理程序过多”问题的解决方案(适合多数键盘事件和鼠标事件)。

移除事件处理程序:在不需要的时候移除事件处理程序,如 btn.onclick = null; 防止内存中留有过时不用的空事件处理程序。

slice、substring 和 substr 的区别

三个方法第一个参数都是指定子字符串开始位置。slice 和 substring 第二个参数指定的是子字符串最后一个字符后面的位置,substr 第二个参数指定的是返回的字符个数。

在参数是负值的情况下,slice 会将传入的负值与字符串长度相加,substr 会将传入的第一个负值与字符串长度相加,第二个参数转换为 0 。substring 会将所有负值参数都转为 0 。

call 和 apply 的区别

这两个方法都是用来改变函数体内 this 对象的值,区别仅在于接收参数的方式不同。call 一个个接收,apply 打包成一个数组接收。

onload 和 ready

ready 表示文档结构已加载完成(不包含图片等非文字媒体文件)

onload 表示包含图片等文件在内的所有元素都加载完成(在 ready 后发生)

原生 AJAX 实现 GET 和 POST 的区别

  1. GET 时要注意缓存问题(xmlHttp.status == 304),POST 时不用考虑
  2. POST 请求必须设置 Content-Type 为 application/x-form-www-urlencoded
  3. GET 时 send() 的参数是 null, POST 时 send 要赋参数

GET 时要注意查询字符串的格式问题,每个参数的名称和值都必须使用 encodeURIComponent() 进行编码。

HTTP 状态码

  1. 1xx,消息
  2. 2xx,成功(200 OK,201 Created)
  3. 3xx,重定向(301 Moved,304 Not Modified)
  4. 4xx,请求错误(401 Unauthorized,403 Forbidden, 404 Not Found)
  5. 5xx,服务器错误(500 Internal Server Error,502 Bad Gateway)

在浏览器中输入一个 url 后发生的事情

  1. 浏览器向服务器发送一个 HTTP 请求
  2. 服务器接收到请求,进行相应处理(可能会从数据库查询数据),生成页面
  3. 服务器将生成的页面作为 HTTP 响应的 body,发送给客户端
  4. 客户端(浏览器)接收到 HTTP 响应,取出 body 里的 HTML 代码,对其进行解析
  5. 解析过程遇到引用的服务器资源(js,css,图片等)再向 Web Server 发送请求,Web Server 查找到对应的资源发送回来

模块化

JavaScript 模块规范有三种:

  1. CommonJS,在 NodeJS 中使用,同步加载完成。
  2. AMD(异步模块定义),采用 require 语句加载模块,第一个参数是要加载的模块数组,第二个参数是加载成功之后的回调函数,代表是 require.js
  3. CMD(通用模块定义),按需加载,代表是 sea.js

优化 JS 性能

a. 使用局部变量,存储全局变量或频繁访问有多级属性的对象,减少查找时间

b. 优化循环,简化循环终止条件,使用减值迭代

c. 优化 DOM 交互

  • 使用文档片段构建 DOM 结构,最小化现场更新(或使用 innerHTML)
  • 使用事件代理

d. 减少语句数量,比如多个变量声明使用一个 var 语句

前端性能优化

部署时:

a. 减少 HTTP 请求(合并CSS、JS、小图片)

b. 使用 CDN 加速

书写时:

a. 使用高效的 CSS,理解 repaint(重绘)和 reflow(重排),尽量避免 reflow

b. 减少 DOM 操作

c. CSS 放头,JS 放尾

跨域

协议、域名、端口任一不同则跨域,解决办法有以下几种:

a. CORS(Cross-Origin-Resource-Sharing,跨域资源共享)

使用自定义的 HTTP 头部(包括请求页面的源信息,如协议、域名、端口号)让浏览器与服务器沟通,从而决定请求或响应是应该成功还是失败。

b. JSONP(JSON with padding,填充式 JSON)

创建一个动态 script 标签,src 属性设置为一个跨域 URL,URL 中指定一个回调,当响应到来时,调用页面中响应的函数处理数据。

c. 修改 document.domain 跨子域

比如主页面嵌入 iframe(子域内),将 iframe 的 document.domain 设置为父域,这样主页面就可以访问子页面的函数。

d. 使用 window.name 来跨域

在一个窗口的生命周期内,所有页面共享 window.name 。

e. 使用后台做代理

将需要跨域的请求发送给本域的后台,后台通过模拟 HTTP 请求去访问其他域的资源。

Web 安全

常见安全问题:

a. SQL 注入

b. XSS(Cross-Site-Scripting)跨域脚本攻击

c. CSRF(Cross-Site-Request-Forgery,跨域请求伪造)

d. 会话劫持

e. Dos攻击

解决方案:

a. 永远不要相信客户端传来的信息,对其进行编码和过滤

b. 验证请求来源

c. 使用 SSL

d. ID 无序化

cookie 是在客户端保存用户信息的一种机制,以键值对的形式保存。

下面是一个存储 cookie 的函数,并将 cookie 名称、值及其过期日期存入 document.cookie 对象。

1
2
3
4
5
6
function setCookie(cookieName, cookieValue, expiredays) {
var exDate = new Date();
exDate.setDate(exDate.getDate() + expiredays);
document.cookie = cookieName + '=' + escape(cookieValue) +
((exDate === null) ? '' : ';expires=' + exDate.toGMTString());
}

null 和 undefined

null 表示没有对象,即此处不应该有值,转为数值为 0undefined 表示缺少值,即此处应该有值,但还未定义,转为数值为 NaN

区分 undefinednull 的方法是用 typeof

1
2
typeof undefined;   // undefined
typeof null; // object

CSS

盒模型

CSS 盒模型包括内容(content)、填充(padding)、边框(border)、边界(margin)四个属性。

标准 w3c 盒模型的 width 指 content width,盒子需要占据的宽度为:
content width + padding*2 + border*2 + margin*2

ie 盒子模型的 content 部分包含了 border 和 padding,盒子需要占据的宽度为:
content width + margin*2

块级元素和行内元素的区别

块级元素:

  • 每个块级元素从新的一行开始,从上到下
  • 可设置宽(默认为父容器100%)、高、行高和边距

行内元素:

  • 和其他元素在同一行,从左到右
  • 不可设置宽(就是其包含文字或图片的宽度)、高、行高和边距

position

static:元素框正常生成

relative:元素框偏移某个距离(相对于其正常位置应该出现的位置),元素仍保持其未定位前的形状

absolute:元素框从文档流完全删除,并相对于其包含块定位,元素定位后生成一个块级框

fixed:类似 absolute,不过其包含块是视窗本身

float

CSS中的定位机制有三种:普通流,浮动,绝对定位。

浮动的框可以左右移动,直到它的外边缘碰到包含框或另一个浮动框的边缘。当浮动框的高度超过包含框时,就会出现包含框不自动伸高来闭合浮动元素(高度坍塌)

闭合浮动的方法:一是在浮动元素的末尾添加一个空元素,设置 clear:both 属性。二是设置父元素 overflow (hidden 或 auto) 或者 display:table 属性来闭合浮动。

BFC

BFC(Block formatting contexts),块级格式化上下文,它是一个独立的布局环境,可以理解为一个盒子。盒子里面物品的摆放是不受外界影响的。

也就是说,BFC中的元素的布局是不受外界影响的(利用这个可以消除浮动元素对其非浮动的兄弟元素和子元素带来的影响)。并且,在一个BFC中,块盒和行盒都会垂直地沿着父元素的边框排列。

display属性值和用法

  • none 不显示
  • block 块级元素
  • inline 行内元素
  • inline-block 行内块级元素
  • list-item 列表项
  • table 块级表格
  • table-cell 表格单元格

display: none 和 visibility: hidden 的区别

  1. 空间占据。使用 display: none ,元素的高度宽度等各种属性都丢失,不再占据空间;使用 visibility: hidden ,元素仅仅是视觉上看不见,宽高仍存在,仍占据空间

  2. 回流和渲染。使用 display: none 产生 reflow 和 repaint,而 visibility: hidden 没有这个产生性能的问题

  3. 株连性。使用 display: none 父节点和子节点全部不可见,使用 visibility: hidden 的话子孙节点使用 visibility: visible 可以显现

文本垂直居中

单行文本:设置 line-heightheight,并使两值相等,再加上 over-flow: hidden 就可以了

多行文本且容器高度可变:给出一致的 padding-bottompadding-top 就行

不考虑IE的话,可以把容器当作表格单元:设置 display: table-cell; vertical-align: middle; height: 500px

在 IE 下,也可设置 postion 为 relative 或 absolute,然后 设置 top 和 left

DIV 居中

方法一,绝对定位居中

1
2
3
4
5
6
7
.wrapper {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
margin: auto;
width: 300px;
height: 300px;
}

方法二,负外边距

1
2
3
4
5
6
7
8
.wrapper {
position: absolute;
top: 50; left: 50;
width: 600px;
height: 400px;
margin-left: -300px; // -width/2
margin-top: -200px; // -height/2
}

布局

两栏布局:

a. 用 position(absolute) + margin-left

b. 用 float(left) + margin-left

c. 用 inline-block(width:25% + width:75%)

d. 用 flex(display:flex + width + flex-column{flex: 1}),只支持 chrome

三栏布局:

a. 负边距(float:left + width:100% + margin-left:-100% + margin-left:-width)

b. float(float:left + float:right + main)

选择器

优先级:ID选择器 > 类选择器 > 标签选择器,如果是同一级别,后出现的优先级高。

px em rem

px 是屏幕设备物理上能显示的最小的一个点

em 是相对于当前对象内文本的尺寸,比如浏览器默认字体尺寸是 16px ,那 1em = 16px,em 会继承父元素的字体大小

rem 相对跟元素的字体尺寸,没有了继承父级尺寸的关系

重绘和重排

浏览器的渲染过程是:

  1. 将 HTML代码 解析成 DOM 树
  2. 将所有样式代码解析成样式结构体
  3. 将 DOM 树和样式结构体组合,构建渲染树
  4. 绘制页面

当页面布局和几何属性(尺寸)改变时需要重排(回流),当元素仅仅是外观改变时,需要重绘。重排必将引起重绘,重绘不一定引起重排。

减少重排重绘的方法:

a. 不要一个个单独修改属性,而是通过 className 或 cssText
b. 离线处理要操作的元素,处理完后一起更新(利用 DocumentFragment,cloneNode,display:none 技术)
c. 不要频繁获取计算后的样式(会触发 flush)

伪类和伪元素

动态伪类:

E:linkE:visitedE:hoverE:activeE:focus

锚点伪类的设置遵循一个顺序(LoVe/HAte,link-visited-hover-active,爱恨原则)

结构伪类:

nth-child(n) 选择父元素第 n 个子元素

nth-of-type(n) 选择父元素具有指定类型的第 n 个元素

状态伪类:

:disabled 设置不可用表单元素的样式

:checked 选中状态的样式

伪元素:

利用伪元素装饰内容而不需要更改 HTML 的内容。

::before 在元素前面加入内容

::after 清除浮动,或者在元素后面加入内容(字符串或改节点的属性 attr(x)

1
2
3
4
5
6
7
.clearfix::after{
content: '',
display: block,
clear: both,
hidden
visibility: hidden
}

::selection 匹配突出显示的文本(鼠标选择文本时的文本)

CSS3

a. font-face

b. rgba

c. border-radius

d. text-shadow

HTML

HTML5

a. Doctype

b. 本地离线存储的支持 Local Storage

c. 用于绘画的 canvas

d. 用于媒介播放的 video audio 元素

d. 语义化的内容元素 nav header footer section article

e. 语义化的表单特性 email time url search date calendar placeholder

坚持原创技术分享,您的支持将鼓励我继续创作!