JS中的块级作用域
1.with 2.try.. catch 3.let, const
变量提升和函数提升
- 包括变量和函数在内的所有声明都会在任何代码被执行前首先
被处理 - 函数声明比变量声明优先提升\
- 只有声明会被提升,变量的赋值或者其他运行逻辑会留在本地
什么叫闭包?
闭包是能够访问另一个函数作用域中变量的函数,创建闭包:将函数作为函数的返回值;将函数作为参数传递。
使用场景:实现对象的数据私有化;代替一些全局变量;
什么叫原型、原型链?
每个函数都有一个prototype属性,这个属性就是原型。原型链就是对象之间的继承链,一个对象通过的prototype指向一个父对象,父对象的prototype又指向另一个对象,最终指向Object对象。这一个关系链就是原型链
如何优化网站性能?
1. Http请求
-
合并js,css文件,雪碧图减少http请求的数量,压缩文件,减少请求的大小;
-
资源文件按需加载;
-
合理使用缓存,sessionStorage,cookie,文件加上MD5戳;
-
数据懒加载,比如PC端可以分页,移动端可以上拉加载
2.HTML方面
-
合理化使用元素,减少不必要的元素
-
避免使用iframe,ifram很消耗资源
3.JS方面
-
js文件放在页面底部,因为渲染网页的顺序是由上至下,如果放在顶部会等待js加载,有可能会出现空白
-
避免在html中直接写js,而是独立一个js文件
-
减少DOM访问和修改。合并多次操作,修改元素的样式会导致重绘,添加删除DOM,修改DOM位置导致重排 (重新排列位置);
-
删除不需要的脚本,合理的设计结构,实现模块化增强复用性;
4.CSS方面
-
样式表放在开头,迅速渲染页面样式;
-
减少行内样式吗,单独css文件可以缓存
-
合理编写css,减少css层级
-
添加一些必要的loading提示
5.server方面
-
使用CDN
-
合理的数据查询语句,适当的缓存
HTTP状态码
1XX 信息状态码
- 100 Continue: 继续发送请求
2XX 成功状态码
-
200 OK: 请求成功
-
201 Created: 创建新资源请求已实现
-
202 Acceped 服务器已接收请求,但是还未处理
-
204 No Content 没有响应内容,跨域option就是204
3XX 重定向状态码
-
300 Muiltiple Choices 请求有多个资源
-
301 Moved Permanently 请求的URL已移除
-
304 Not Mofdified 资源未被修改
4XX 客户端错误状态码
-
400 Bad Request 发送了一个错误请求(参数确实或错误)
-
401 Unauthorized 未授权
-
403 Forbidden 请求被拒绝
-
404 Not Found 找不到资源
5XX 服务端错误状态码
-
500 internal Server Error 服务器发生错误
-
502 Bad Gateway 代理出错
Vue相关
a. vue和Angularjs的区别
-
AngularJS采用双向数据绑定,vue默认使用单向数据绑定
-
vue中也有双向数据绑定,angularjs是基于脏检查,而vue是基于getter和setter
-
AngularJS属于MVVM框架,而vue相当于view层
-
vue更容易上手,API完整有完整的生命周期;
b. vue和Jquery的区别
-
vue采用数据驱动,尽量避免DOM操作,Jquery使用核心是DOM操作 ;
-
Jquery本质上是封装了DOM操作的函数库,vue属于一个框架;
c. vue的原理
- 采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调
Object.defineProperty(person, 'name', {
set: function(newVal) {
temp['name'] = newVal;
console.log('为person设置新的姓名:' + newVal);
},
get: function() {
var _name = temp['name'] || '默认姓名';
console.log('获取person的姓名:' + _name);
return _name;
}
});// 当person复制或取值的时候回调用set,get,
d. vue生命周期
-
一共分为8个阶段:创建前/后,载入前/后,更新前/后,销毁前/后
-
created阶段数据已经准备好了,但是html还没有渲染完成
-
mounted html已经渲染完成
-
destory 解除事件监听和dom绑定,但是dom结构还在
e. vuex
- vuex作用:管理Vue组件的状态(当出现多个视图组件依赖同一个状态,来自不同视图的行为需要变更同一个状态。)
排序方式
- 冒泡排序
相邻元素两两比较
function bubbleSort(arr) {
var length = arr.length;
for(let i = 0; i < length; i++) {
for(let j = 0; j < length - 1; j++) {
if(arr[j + 1] < arr[j]) {
let tem = arr[j+ 1];
a[j+ 1] = a[j];
a[j] = tem;
}
}
}
return arr;
}
- 选择排序
选择最小的
function selectSort(arr) {
let length = arr.length;
let minIndex, temp;
for(let i = 0; i < length; i++) {
minIndex = i;
for(let j = i + 1; j < length; j++) {
if(arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if(i != minIndex) {
temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
}
}
return arr;
}
3.插入排序
类似打牌,每选择一个元素就找适合它的位置
function insertSort(arr) {
let length = arr.length;
let newArr = [];
for(let i = 1; i < length; i++) {
let key = arr[i];
let j = i - 1;
while(arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
return arr;
}
清除浮动的方式
-
overflow:hidden
-
容器元素最后添加元素,使用clear:both
-
伪元素
.clearfix:after{
content:"";//设置内容为空
height:0;//高度为0
line-height:0;//行高为0
display:block;//将文本转为块级元素
visibility:hidden;//将元素隐藏
clear:both//清除浮动
}
.clearfix{
zoom:1;为了兼容IE
}
水平垂直居中的方式
- margin: auto; 必须知道高度
.item {
postion: absoulate;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
- margin 高宽一半; 必须知道高度和宽度
.item {
postion: absoulate;
top: 50%;
left: 50%;
height: 100px;
width: 100px;
margin-top: -50px;
margin-left: -50px;
}
- transform; 不需要知道高度和宽度
.item {
postion: absoulate;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
- flex; 兼容性问题
.item {
dispaly: flex;
justify-content:center;
align-items: center;
}
实现深度克隆
function deepClone(obj) {
var toString = Object.prototype.toString;
// null, undefined, {}, function
if(!obj || typeof obj !== 'object') {
return obj;
}
if(toString.call(obj) === '[object Date]') {
return new Date(obj.getTime());
}
if(toString.call(obj) === '[object RegExp]') {
var flags = [];
if(obj.global) {
flags.push('g');
}
if(obj.multiline) {
flags.push('m');
}
if(obj.ignoreCase) {
flags.push('i');
}
return new RegExp(obj.source, flags.join(''))
}
let temp = obj instanceof Array ? [] : {};
for(var i in obj) {
if(obj.hasOwnProperty(i)) {
temp[i] = deepClone(obj[i]);
}
}
return temp;
}// 优化, 可以尾部调用递归
数组去重
- 利用对象属性唯一
function unique(array) {
let obj = {};
let newArray = [];
for(let i = 0; i < array.length; i++) {
if(!obj[array[i]]) {
obj[array[i]] = true;
newArray.push(array[i]);
}
}
return newArray;
}
2.两层循环 splice
function unique2(arr) {
let length = arr.length;
for(var i = 0; i < length; i++) {
for(var j = i + 1; j < length; j++) {
if(arr[j] == arr[i]) {
arr.splice(j, 1);
length --;
j --;
}
}
}
return arr;
}
3.ES6 set 去重
function unique3(arr) {
return Array.from(new Set(arr));
// return (...new Set(arr)) 扩展运算符
}
内存泄露
- 不再用到的内存,没有及时释放就叫内存泄露
- 垃圾回收机制:标记清除(最常用),和引用计数
- 常见内存泄露情况:
- 意外的全局变量,比如未定义,直接变量提升(采用严格模式防止)
- 闭包过多,闭包中用到的变量不会被回收
- dom清空或删除时,事件未清除导致的内存泄漏,及时移除事件
- 循环引用(引用计数永远是1)
事件流阶段
捕获阶段、目标阶段、冒泡阶段
Promise
- Promise 好处
将异步接口以同步的流程表现出来 - Promise对象的两个特点:
- 对象的状态不受外界影响;
- 一旦状态改变,就
- Promise 的三个状态
pending,resolved,rejected
Promise状态改变只有两种可能:从pending到fulfilled,从pending到rejected - Promise 内部的错误不会影响到 Promise 外部的代码(Promise会吃掉错误)
- Promise.resolve 将现有对象转化为Promise对象
Promise.resolve('foo') // 等价于 new Promise(resolve => resolve('foo'))
Promise.resolve方法的参数分成四种情况。
(1) 参数是一个Promise对象
原封不动返回
(2) 参数是一个 thenable对象(有then属性方法)
会将对象转化为Promise对象,然后立即执行其中的then方法
let thenable = {
then: function(resolve, reject) {
resolve(222);
}
};
Promise.resolve(thenable)
.then(res => console.log(res));
(3) 参数没有then方法, 或者根本不是对象
会返回一个新的Promise对象,状态为resolved
const p = Promise.then('hello');
p.then(function(s) {
console.log(s);
}); // hello
(4) 不带任何参数时,直接返回一个resolved状态的Promise对象
因此可以使用Promise.then() 创建一个新的Promise对象
- 使用Promise封装ajax
let mineAjax = function(url, method, data) { let promise = new Promise(function(resolve, reject) { const handler = function() { if(this.readyState === 4 && this.status === 200) { resolve(this.responce); } else { reject(new Error(this.statusText)); } }; const client = new XMLHttpRequest();// new 一个 ajax对象 data = getQueryString(data);// 对象数据转'&'连接的字符串 if(method == 'post') { client.open(method, url); client.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');// post 要设置header if(data) { client.send(data); } else { client.send(); } } if(method == 'get') { url += data; client.open(method, url); client.send(); } client.onreadystatechange = handler; client.responseType = 'json'; }); return promise; } function getQueryString(query) { let result = []; for(let key in query) { result.push(`${key}=${query[key]}`); } if(result.length > 0) { return result.join('&'); } } mineAjax('testurl", 'post', {data: test}).then(function(res){ console.log(res); }, function(error) { console.log(error); });
- Promise.prototype.then
- then 是写在 promise原型上
- then方法返回的是一个新的Promise实例
- 链式写法,前一个then的返回值下一个then的参数
js写原生ajx
- new XMLHttpRequest;
- 使用open方法,设置请求方法(get/post)、url
- 设置发送数据,数据为(a=1&b=2)的格式
- 如果是post请求设置请求头 setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
- send, 如果有数据 send(data),没有send();
- 服务器响应事件,onreadystatechange,当readyState == 4 && status == 200的时候表示响应成功
- ajax readState
0 - (未初始化)还没有调用send()方法
1 - (载入)已调用send()方法,正在发送请求
2 - (载入完成)send()方法执行完成,已经接收到全部响应内容
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了
设计模式
- 单体模式
概念: 单体是一个用来划分命名空间,并将一批属性和方法组织在一起的对象
应用: 将代码封装在一个对象中,只暴露一个入口
好处:- 可以用来划分命名空间,减少全局变量的数量;
- 使用单例模式可以使代码组织更为一致,便于阅读和维护
- 可以被实例化,且实例化一次
var Singleton = {
attribute: true,
method1: function() {},
method2: function() {}
};
- 工厂模式
概念: 用于创建对象实例,封装实例创建过程,只关心创建结果
应用:处理一些共享相同属性的组件,或者对象,比如提示框;AngularJS factory
缺点: 没有解决对象的识别问题,都是object
function animal(opts) {
var obj = new Object();
obj.name = opts.name;
obj.color = opts.color;
obj.getInfo = funtion() {
return name;
}
return obj;
}
var cat = animal({name: '波斯猫', color: '白色'});
- 构造函数模式
概念: 用于创建特定类型的对象
优点: 解决了工厂模式无法识别类型的问题(instanceof Animal == true)
缺点: 有些公共方法,需要重复定义
function Animal(name, color) {
this.name = name;
this.color = color;
this.getName = function() {
return this.name;
}
}
var cat = new Animal('猫', '白色');
cat.getInfo();
- 原型模式
概念: 将属性都放在原型上;
优点: 所有所有实例可以共享他的属性和方法
缺点: 共享属性和方法,导致一个实例更改属性或方法就会影响其他实例
function Animal() {}
Animal.name = '猫';
Animal.color = '白色';
var cart1 = new Animal();
var cart2 = new Animal();
- 混合模式(构造函数模式和原型模式结合)
概念:构造函数负责属性,原型模式负责公共方法或属性function Animal(name, color) { this.name = name; this.color = color; } Animal.prototype.getInfo = function() { return this.name + ' ' + this.color; }
- 创建对象的方式:
- 对象字面量和Object构造函数
- 工厂模式:抽象了对象的实现过程,但是无法知道对象的类型
- 构造函数模式:new 操作符,可以判断实例类型(即instanof可以判断),缺点无法使用公共属性
- 原型模式:将公共属性添加到prototype中;
- 组合使用构造函数模式和原型模式:构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性。使用最广泛的一种方法
- 动态原型模式: 把初始化原型的过程也封装在构造函数中;
- 发布订阅者模式
概念: 一对多的映射关系,让多个观察者对象同时监听某一个主题对象,当该对象改变时,依赖于它的对象都将得到通知;
优点:支持简单的广播通信,对象改变会自动通知订阅过的对象
发布者和订阅者的耦合性降低
缺点:创建订阅者需要消耗一定的时间和内存
跨域
为什么跨域:XHR对象只能访问同一个域中的资源,为了防止某些恶意行为,但是有时候需要跨域访问
- 图像Ping
- 一个网页可以从任何网页中加载图像
- 常用于跟踪用户点击页面或动态广告曝光次数(1px图片)
- JSONP (JSON with padding)
- JSONP由回调函数和数据组成
- 因为script 可以不受限的从其他域获取资源;
- 有安全问题,确定JSONP是否请求失败不容易;
- CORS (cors origin resource sharing)
- 代理 nginx转发
TCP 三次握手
TCP核心思想:既要保证数据可靠传输,又要提高传输的效率,三次握手刚好可以满足
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:客户端发送syn包到服务器;
第二次握手:服务器确认客户端的sync包,同时发送一个sync + ack包到客户端
第三次握手:客户端收到服务器发的包,向服务器发送确认包ACK完成三次握手
TCP和UDP的区别
TCP面向有链接,能正确处理丢包, UDP面向无连接,不管对方有没有收到
HTTP
HTTP是建立在TCP协议基础上的,http是一种短连接,是一种无状态的连接
从输入URL到页面加载发生了什么
1.输入URL,
- 浏览器根据URL查找是否有缓存,并且判断缓存是否过期,如果没过期则从缓存中读取,如果过期则需要重新读取
- DNS查找域名的IP地址
- 先从浏览器缓存中找,在从操作系统缓存中找,再从路由器缓存中找
- 没有缓存,则进行DNS递归查找
- 同服务器建立TCP连接,然后发起http请求
- 服务器收到请求并解析,将请求转发到服务程序;
- 服务程序读取请求并作出响应;
- 服务器通过TCP连接发送回浏览器;
- 浏览器接收响应,检查状态码,作出响应;
- 解析HTML文档,构建DOM树结构,下载图片、视频、css、js资源等,构建CSSOM树
10.根据DOM树和CSSOM树构建渲染树, 执行js脚本 - 最后显示HTML
浏览器缓存机制
浏览器缓存就是把一个已经请求过的web资源(html,图片,js等)拷贝一份副本存储在浏览器中;
- 浏览器缓存的控制
- 使用HTML Meta标签
- 使用和缓存有关的http报文
<meta http-equiv="Pragma" content="no-cache">
项目相关
- Angularjs和Vue你觉得区别在哪里?
- 从使用上看,Vue使用更为方便,有完整的api包括生命周期,文档也个更为齐全
- Angularjs指令和组件没有区分开,都是用directive,而Vue是完全分开的
- Vue性能更好,Angularjs 的双向绑定是基于脏检查的 ,当 watcher 越来越多时会变得越来越慢,因为作用域内的每一次变化,所有 watcher 都要重新计算。则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter;
a. 脏值检查: 就是不关心你如何以及何时改变的数据,只关心在特定的检查阶段(UI事件,ajax事件, timeout 延迟事件),数据是否改变。
b. angularjs賍值检查的实现:
每一个绑定到UI上的数据 都拥有一个对应的$watch对象,这个对象会被push到watch list中, $watch包括两个函数属性
watch = {
name: '', // 当前watch的对象
getNewValue: function($scope) {// 得到新值
return newValue;
},
listener: function(newValue, oldValue) {// 当数据发生改变时候需要执行的操作
...
}
};
c. 手动出发脏检查,$apply进入angular上下文,$digest触发脏检查
gulp和webpack的区别
两者不应该拿来比较,
gulp属于前端流程优化工具,它可以自动刷新页面、压缩技术,css,编译less,自动化
而webpack是模块化方案,是一个前端资源加载/打包工具,从官网的图片就可以看出Webpack 可以将多种静态资源 js、css、less 转换成一个静态文件,减少了页面的请求
this
- this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
- this取值情况分为4种情况:
- 构造函数,如果函数作为构造函数(new),那么this指向new出来的对象
- 函数作为对象的一个属性,并且作为对象的一个属性被调用的时候,this指向该对象(隐式绑定);
- 函数使用call或apply调用的时候,this的值就去传入对象的值;(显示绑定)
- 全局并且调用普通函数,this指向window(nodejs中指向global)
- 箭头函数根据外层作用域(函数或者全局)决定this
作用域
- 作用域在函数定义的时候就已经确定,而不是函数调用时确定
- 作用域中变量的值是在执行过程中产生和确定的
- 自由变量跨作用域取值要去创建函数的作用域找
执行上下文
执行上下文指的是以下三种数据的准备情况:
- 变量(包括函数表达式)的变量声明,默认赋值为undefined
- this的赋值;
- 函数声明的赋值
通俗的讲就是把将要用到的所有变量都实现声明和赋值
函数每被调用一次,都会产生一个新的执行上下文环境
处于活动状态的执行上下文环境只有一个,执行不同上下文的过程,是一个压栈出栈的过程——执行上下文栈
常用正则
- 去除空格
- 所有空格
replace(/\s*/g, ''); - 去除两头空格
replace(/^\s|\s$/g, ''); - 去除左边空格
replace(/^\s*/g, '') - 去除右边空格
replace(/\s*$/g, '')
- 数字
- 整数 /^\d+$/;
- 数字 /^\d*.?\d+$/
圣杯布局和双飞翼布局
- 圣杯布局
<div class="container">
<div class="middle"><h4>中间弹性区</h4></div>
<div class="left"><h4>左边栏</h4></div>
<div class="right"><h4>右边栏</h4></div>
</div>
<style>
.container {
height: 200px;
overflow: hidden;
padding: 0 200px;
}
.middle {
width: 100%;
height: 200px;
background-color: deeppink;
float: left;
}
.left {
width: 200px;
height: 200px;
background-color: blue;
float: left;
margin-left:-100%;
position: relative;
left: -200px;
}
.right {
width: 200px;
height: 200px;
background-color: darkorchid;
float: left;
margin-left:-200px;
position: relative;
right: -200px;
}
</style>
- 双飞翼布局
<div class="container2">
<div class="middle2"><div><h4>中间弹性区</h4></div></div>
<div class="left2"><h4>左边栏</h4></div>
<div class="right2"><h4>右边栏</h4></div>
</div>
.container2 {
height: 200px;
overflow: hidden;
margin-top: 20px;
}
.left2 {
width: 200px;
height: 200px;
background-color: green;
float: left;
margin-left: -100%;
}
.right2 {
width: 200px;
height: 200px;
background-color: red;
float: left;
margin-left: -200px;
}
.middle2 {
width: 100%;
height: 200px;
float: left;
background-color: orange;
}
.co {
margin: 0 200px;
}
清除浮动
1、clear清除浮动(添加空div法)
在浮动元素下方添加空div,并给该元素写css样式: {clear:both;height:0;overflow:hidden;}
2、方法:给浮动元素父级设置高度
3、父元素overflow:hidden
overflow: hidden;
*zoom: 1;
- after伪类
.clear:after{content:' ';display:block;clear:both;height:0;overflow:hidden;visibility:hidden;}
.clear{zoom:1;}
网友评论