前端总结一

javascript

1.做用域与做用域链

  • 做用域是根据名称查找变量的一套规则,用于肯定在何处以及如何查找变量(标识符)。若是查找的目的是对变量进行赋值,那么就会使用 LHS 查询;若是目的是获取变量的值,就会使用 RHS 查询。
  • 当一个块或函数嵌套在另外一个块或函数中时,就发生了做用域的嵌套,造成了做用域链。其规则就是,在当前做用域中没法找到某个变量时,引擎就会在外层嵌套的做用域中继续查找,直到找到该变量,或抵达到全局做用域为止,此时不管是否找到该变量,都会中止查到。

所以,变量可分为本地变量与全局变量:javascript

  1. 全局范围:代码执行前,变量、函数声明会提高
  2. 函数范围:代码执行前,函数、变量,this、argument 会提高。

注意,函数提高由优先于变量提高,函数表达式不会提高。php

2.做用域提高

举个例子, var a = 2;JavaScript 引擎会把它分为两个单独的声明,分别是css

var a a = 2html

第一个是编译阶段的任务,而第二个则是执行阶段的任务。 不管做用域中的声明出如今什么地方,代码执行前首先进行编译处理。 能够将这个过程形象地想象成全部的声明(变量和函数)都会被“移动”到各自做用域的最顶端,这个过程被称为提高。前端

3.词法做用域

做用域是由书写代码时函数声明的位置来决定的。编译的词法分析阶段基本可以知道所有标识符在哪里以及是如何声明的,从而可以预测在执行过程当中如何对它们进行查找。html5

4.闭包

4.1什么是闭包

当函数能够记住并访问所在的词法做用域,即便函数是在当前词法做用域以外执行,这时就产生了闭包。java

4.2闭包有什么用

闭包在实际开发中主要用于封装变量,收敛权限,使用场景:node

4.2.1函数做为返回值webpack

function isFirstLoad(){
      var _list = []//私有变量
      return function(id){
        if (_list.indexOf(id)>=0){
          return false
        }else{
          _list.push(id)
          return true
        }
      }
    }

    var firstLoad = isFirstLoad()
    firstLoad(10) //true
    firstLoad(10) //false
    firstLoad(20) //true
    //在isFirstLoad函数外面,根本不能修改 _list 的值!
复制代码

4.2.2函数做为参数传递:es6

var fn;
    function foo() {
     var a = 2;
     function baz() {
     console.log( a );
     }
     fn = baz; // 将 baz 分配给全局变量
    }
    function bar() {
     fn(); // 妈妈快看呀,这就是闭包!
    }
    bar(); // 2
复制代码

将内部函数传递到所在的词法做用域之外,它都会持有对原始定义做用域的引用,不管在何处执行这个函数都会使用闭包。

5.原型与原型链

5.1什么是原型和原型链

原型:Prototype 是个对象,只有函数上有。它是用来存储对象的属性(数据和方法)的地方,是实现JavaScript 原型继承的基础。

原型链:

  • 每一个函数都能构建一个对象,该对象的__proto__ 属性指向函数的原型对象(obj. __proto__=== Foo.Prototype
  • 原型对象本质也是一个对象,也是由另外一个构造函数构造出来的,也指向那个构造函数的原型对象
  • 以上,造成一个链式结构,就称为原型链。

5.2原型继承的方式:

// ES6 以前须要抛弃默认的 Bar.prototype

Bar.ptototype = Object.create( Foo.prototype ); // ES6 开始能够直接修改现有的 Bar.prototype Object.setPrototypeOf( Bar.prototype, Foo.prototype ); extends Object.getPrototype(); Object.setPrototype()等;

若是忽略掉 Object.create(..) 方法带来的轻微性能损失(抛弃的对象须要进行垃圾回 收),它实际上比 ES6 及其以后的方法更短并且可读性更高。不过不管如何,这是两种完 全不一样的语法

5.3原型链

[[Prototype]] 机制就是存在于对象中的一个内部连接,它会引用其余对象。 一般来讲,这个连接的做用是:若是在对象上没有找到须要的属性或者方法引用,引擎就 会继续在 [[Prototype]] 关联的对象上进行查找。同理,若是在后者中也没有找到须要的 引用就会继续查找它的 [[Prototype]],以此类推。这一系列对象的连接被称为“原型链”。

6.this

6.1 this是什么

当一个函数被调用时,会建立一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this就是记录的其中一个属性,会在函数执行的过程当中用到。

6.2 this绑定及优先级

若是要判断一个运行中函数的 this 绑定,就须要找到这个函数的直接调用位置。找到以后 就能够顺序应用下面这四条规则来判断 this 的绑定对象。

  1. 由 new 调用?绑定到新建立的对象。
  2. 由 call或者apply(或bind)调用?绑定到指定的对象。
  3. 由上下文对象调用?绑定到那个上下文对象。
  4. 默认:在严格模式下绑定到 undefined,不然绑定到全局对象

ES6 中的箭头函数并不会使用以上四条标准的绑定规则,而是根据当前的词法做用域来决定 this,具体来讲,箭头函数会继承外层函数调用的 this 绑定(不管 this 绑定到什么)。

6.3 绑定例外

  • 间接引用

    function foo() { 
         console.log( this.a );
     }
     var a = 2; 
     var o = { a: 3, foo: foo }; 
     var p = { a: 4 };
     o.foo(); // 3
     (p.foo = o.foo)(); // 2
    复制代码

赋值表达式 p.foo = o.foo 的返回值是目标函数的引用,所以调用位置是 foo() 而不是p.foo() 或者 o.foo(),这里会应用默认绑定。

  • 忽略的this

    function foo() { 
      console.log( this.a );
     }
     var a = 2;
     foo.call( null ); // 2
    复制代码

若是你把 null 或者 undefined做为this的绑定对象传入call、apply或者bind,这些值在调用时会被忽略,实际应用的是默认绑定规则.

6.4 当this遇到return

  • return的是基本类型:

    function fn()  {  
     this.user = '追梦子';  
     return 1;
     }
     var a = new fn;  
     console.log(a.user); //追梦子
    复制代码
  • return的是对象:

    function fn()  {  
     this.user = '追梦子';  
     return function(){};
     }
     var a = new fn;  
     console.log(a.user); //undefined
    复制代码

若是返回值是一个对象,那么this指向的就是那个返回的对象,若是返回值不是一个对象那么this仍是指向函数的实例。

6.5 改变this绑定

#####6.5.1 call() 语法:

fun.call(thisArg, arg1, arg2, ...)
复制代码

1、使用call方法调用父构造函数:

function Product(name, price) {
      this.name = name;
      this.price = price;
    }
    
    function Food(name, price) {
      Product.call(this, name, price);
      this.category = 'food';
    }
    
    var cheese = new Food('feta', 5);//Food {name: "feta", price: 5, category: "food"}
复制代码

2、使用call方法调用函数而且指定上下文的'this'

function greet() {   
    var reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' '); 
    console.log(reply); }
     
    var obj = {   
        animal: 'cats', sleepDuration: '12 and 16 hours'
    };
     
    greet.call(obj);  // cats typically sleep between 12 and 16 hours
复制代码

3、使用call方法调用函数而且没有肯定第一个参数,this的值将会被绑定为全局对象,严格模式下this的值将会是undefined。

6.5.2 apply()

语法:

func.apply(thisArg, [argsArray])
复制代码
/* 找出数组中最大/小的数字 */
var numbers = [5, 6, 2, 3, 7];
/* 应用(apply) Math.min/Math.max 内置函数完成 */
var max = Math.max.apply(null, numbers); /* 基本等同于 Math.max(numbers[0], ...) 
var min = Math.min.apply(null, numbers)
复制代码
6.5.3 bind()

语法:

function.bind(thisArg[, arg1[, arg2[, ...]]])
复制代码

1、建立绑定函数

this.x = 9;    
    var module = {
      x: 81,
      getX: function() { return this.x; }
    };
    var retrieveX = module.getX;
    retrieveX();   // 返回9 
    
    // 建立一个新函数,把 'this' 绑定到 module 对象
    var boundGetX = retrieveX.bind(module);
    boundGetX(); // 81
复制代码

2、预设的初始参数

function list() {
  return  Array.prototype.slice.call(arguments);
}
var leadingThirtysevenList = list.bind(null, 37);
var list = leadingThirtysevenList(1, 2, 3); 
// [37, 1, 2, 3]
复制代码

7.对象的拷贝

7.1 浅拷贝

7.1.1 赋值=

以赋值的形式拷贝引用对象,仍指向同一个地址,修改时原对象也会受到影响

const originArray = [1,2,3,4,5];
const cloneArray = originArray;
console.log(cloneArray); // [1,2,3,4,5]
cloneArray.push(6);
console.log(cloneArray); // [1,2,3,4,5,6]
console.log(originArray); // [1,2,3,4,5,6]
复制代码
7.1.2 (...)//展开运算符

7.2 深拷贝

彻底拷贝一个新对象,修改时原对象再也不受到任何影响:

7.2.1 JSON.parse(JSON.stringify(obj))//性能最快
/*
JSON.parse 是将一个 JSON 字符串转成一个 JavaScript 值或对象
JSON.stringify 是将一个 JavaScript 值转成一个 JSON 字符串
*/
const originArray = [1,2,3,4,5];
const cloneArray = JSON.parse(JSON.stringify(originArray));
console.log(cloneArray === originArray); // false
复制代码

注意: 一、具备循环引用的对象时,报错; 二、当值为函数、undefined、或symbol时,没法拷贝;

7.2.2 object.assign()
const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
copy.a = 2
console.log(copy) //{ a: 2 }
console.log(obj) //{a: 1}
复制代码
7.2.3 递归进行逐一赋值

8.new运算符的执行过程

  • 新生成一个对象
  • 连接到原型: obj.proto = Con.prototype
  • 绑定this: apply
  • 返回新对象(若是构造函数有本身 retrun 时,则返回该值)

9.代码的复用

当你发现任何代码开始写第二遍时,就要开始考虑如何复用。通常有如下的方式:

  • 函数封装
  • 继承
  • 复制 extend
  • 混入mixin
  • 借用apply/call

10.继承

10.1 最有模式:圣杯模式

//c是目标,p是继承源
var inherit = (function(c,p){
//F函数是一个闭包,仅用作一个缓冲
	var F = function(){};
	return function(c,p){
		F.prototype = p.prototype;
		/*使对象C试图修改自身属性时仅仅是以F函数做为对象进行修改,而不会影响到其余对象 */
		c.prototype = new F();
		//令目标函数c知道本身的原型
		c.uber = p.prototype;
		c.prototype.constructor = c;
	}
})();

复制代码

10.2 ES6语法糖

class/estends

11.数据类型

11.1 类型的7种分类

String、Number、Boolean、object、Symbol、Null、Undefined

  • Undefined:未定义;
  • Null:定义了但为空;
  • String:最大长度为2^53-1,指的是UTF16编码长度;
  • Number:浮点数的比较 console.log(Math.abs(0.1+0.2-0.3)<=Number.EPSILON)
  • Symbol:用于api的扩展
/*运算符提供了装箱操做,它会根据基础类型构造一个临时对象,使得咱们能在基础类型上调用对应对象的方法。*/
    Symbol.prototype.hello = () => console.log("hello");

   var a = Symbol("a");
   console.log(typeof a); //symbol,a 并不是对象
   a.hello(); //hello,有效

复制代码
  • Object:内置对象以下 Object,Array,Boolean,Number,String,Function,Data,Regexp,Error.

11.2 类型转换

11.2.1 运算符号转换

JS 中在使用运算符号或者对比符时,会自带隐式转换,规则以下:

  • -、*、/、% :一概转换成数值后计算
  • +:

数字 + 字符串 = 字符串, 运算顺序是从左到右 数字 + 对象, 优先调用对象的valueOf -> toString 数字 +boolean/null -> 数字 数字 + undefined -> NaN

  • 1.toString() === '1'
  • {}.toString() === '[object object]'
  • NaN !== NaN
  • +undefined 为 NaN
  • +null=0,+""=0
  • 加法运算只要其中一个是字符串,那么另一个也会转换为字符串,而后进行字符串的拼接!
11.2.2 装箱转换

每一种基本类型 Number、String、Boolean、Symbol在对象中都有对应的类,所谓装箱转换,正是把基本类型转换为对应的对象。

全局的 Symbol 函数没法使用new来调用,但咱们仍可利用装箱机制来获得一个 Symbol 对象

var symbolObject = (function(){ return this; }).call(Symbol("a"));

    console.log(typeof symbolObject); //object
    console.log(symbolObject instanceof Symbol); //true
    console.log(symbolObject.constructor == Symbol); //true

复制代码
11.2.3 ‘== ’ 转换

若是两边类型不一样,会有隐式转换发生。总结以下: 1. 首先看双等号先后有没有NaN,若是存在NaN,一概返回false 2. 若是有true或false,转换为1或0,再比较。 3. 若是有引用类型,优先调用valueOf。 4. 数字和字符串,转化为数字再比较。 5. null和undefined,相等。 6. 5,其他都不相等。

console.log(undefined == false); // false
	console.log(null == false);   // false
	console.log(0 == false);     // true
	console.log(NaN == false);    // false
	console.log("" == false);    // true
	/*
	0 == false之因此为true根据第2条。
    "" == false之因此为true根据第2条,变成了""==0,再根据第4条。*/
console.log([[2]] == '2')   //true
/*
[[2]]的valueOf是对象自己,不是基本类型。尝试调用toString的结果是'2'。所以变成了'2'和数字2的比较。根据第2条,相等*/
复制代码

#####11.2.4 类型转换的6个假值 0/+0,-0,“”,false,undefined,NaN.

11.3 类型判断

  • 基本类型(null): 使用 String(null);

  • 基本类型(string / number / boolean / undefined) + function: 直接使用 typeof便可;

  • 其他引用类型(Array / Date / RegExp /Error): 调用toString

  • 通用但很繁琐的方法:prototype alert(Object.prototype.toString.call(d) === ‘[object Date]') -------> true;

  • 判断封装:

let class2type = {}
'Array Date RegExp Object Error'.split(' ').forEach(e => class2type[ '[object ' + e + ']' ] = e.toLowerCase()) 

function type(obj) {
    if (obj == null) return String(obj)
    return typeof obj === 'object' ? class2type[ Object.prototype.toString.call(obj) ] || 'object' : typeof obj
}
复制代码

12.模块化

一般,咱们在浏览器中使用ES6的模块化支持,在 Node 中使用 commonjs 的模块化支持,分类以下:

  • es6: import / export
  • commonjs: require / module.exports / exports
  • amd: require / defined

其中,require与import的区别:

  • require支持 动态导入,import不支持,正在提案(babel下可支持)
  • require是同步导入,import属于异步导入
  • require是值拷贝,导出值变化不会影响导入值;import指向 内存地址,导入值会随导出值而变化

13.ES6/ES7

因为 Babel 的强大和普及,如今 ES6/ES7 基本上已是现代化开发的必备了。经过新的语法糖,能让代码总体更为简洁和易读。

13.1 声明

  • let / const:块级做用域、不存在变量提高、暂时性死区、不容许重复声明
  • const: 声明常量,没法修改

13.2 解构赋值

####13.3 class / extend: 类声明与继承

13.4 Set / Map: 新的数据结构

13.5 异步解决方案:

  • Promise的使用与实现
  • generator: yield: //暂停代码 next(): //继续执行代码
function* helloWorld() {
  yield 'hello';
  yield 'world';
  return 'ending';
}
const generator = helloWorld();
generator.next()  // { value: 'hello', done: false }
generator.next()  // { value: 'world', done: false }
generator.next()  // { value: 'ending', done: true }
generator.next()  // { value: undefined, done: true }

复制代码
  • await / async:是generator的语法糖,babel中是基于promise实现。
async function getUserByAsync(){
   let user = await fetchUser();
   return user;
}
const user = await getUserByAsync()
console.log(user)
复制代码

14.babel编译原理

  • babylon 将 ES6/ES7 代码解析成 AST(抽象语法树:Abstract Syntax Tree)
  • babel-traverse 对 AST 进行遍历转译,获得新的 AST
  • 新 AST 经过 babel-generator 转换成 ES5

15.函数柯里化

柯里化是一种在多有参数被提供前,挂起或‘延迟’函数执行,将多参函数转化为一元函数序列的编程技术,本质是词法做用域(闭包)原理。

var add = function(x) {
  return function(y) {
    return function(z) {
      return x + y + z;
    }
  }
}

var addOne = add(1);
var addOneAndTwo = addOne(2);
var addOneAndTwoAndThree = addOneAndTwo(3);
console.log(addOneAndTwoAndThree);  //6

//非柯里化实现参数求和
let add = function(...arg) {
  //得到参数数组
  let _args = [].slice.call(arguments);
  return _args.reduce((sum, i) => {
    return sum + i;
  });
};
console.log(add(1, 2, 3));//6
复制代码

16.AJAX

16.1 AJAX技术的核心 - XMLHttpRequest对象

XMLHttpRequest对象是浏览器提供的一个API,用来顺畅地向服务器发送请求并解析服务器响应,整个过程当中,浏览器页面不会被刷新。

XMLHttpRequest只是一个JavaScript对象,确切的说,是一个构造函数,它是由客户端(即浏览器)提供的(而不是JavaScript原生的),除此以外,它有属性,有方法,须要经过new关键字进行实例化。

16.2 建立一个XML对象的实例:

const xhr = new XMLHttpRequest() 该实例的属性,方法有:

  • 方法
open() //准备启动一个AJAX请求;
setRequestHeader() //设置请求头部信息;
send() //发送AJAX请求;
getResponseHeader() //得到响应头部信息;
getAllResponseHeader() //得到一个包含全部头部信息的长字符串;
.abort() //取消异步请求;
复制代码
  • 属性
responseText //包含响应主体返回文本;
responseXML /*若是响应的内容类型时text/xml或application/xml,该属性将保存包含着相应数据的XMLDOM文档;*/
status //响应的HTTP状态;
statusText //HTTP状态的说明;
readyState //表示“请求”/“响应”过程的当前活动阶段
复制代码

另外,浏览器还为该对象提供了一个onreadystatechange监听事件,每当XML实例的readyState属性变化时,就会触发该事件的发生。其可取的值以下:

0:未初始化 -- 还没有调用.open()方法; 1:启动 -- 已经调用.open()方法,但还没有调用.send()方法; 2:发送 -- 已经调用.send()方法,但还没有接收到响应; 3:接收 -- 已经接收到部分响应数据; 4:完成 -- 已经接收到所有响应数据,并且已经能够在客户端使用了;

16.3 GET请求 与 POST请求

16.3.1 GET

GET请求用于获取数据,有时候咱们须要获取的数据须要经过“查询参数”进行定位,在这种状况下,咱们会将查询参数追加到URL的末尾,令服务器解析。 const query = "example.php?name=tom&age=24"//"?name=tom&age=24"便是一个查询参数

16.3.2 POST

POST请求用于向服务器发送应该被保存的数据,所以POST请求自然比GET请求多须要一份须要被保存的数据,发送的数据会做为.send()方法的参数最终被发往服务器。

须要注意,.send()方法的参数是不可为空的,也就是说,对于不须要发送任何数据的GET请求,也须要在调用.send()方法时,向其传入null值;

16.4 Open()

.open()方法接收三个参数:请求方式,请求URL地址和是否为异步请求的布尔值。

// 该段代码会启动一个针对“example.php”的GET同步请求。
xhr.open("get", "example.php", false)
复制代码

16.5 一个异步的GET请求代码以下:

const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
    if(xhr.readyState === 4 && xhr.status === 200){
        alert(xhr.responseText);
    }
}
xhr.open("get", "example.php", true)
xhr.send(null)
复制代码

注意:为了确保跨浏览器的兼容性,必需要在调用.open()方法以前指定事件处理程序。

17.JavaScript单线程和异步机制

所谓的单线程,即程序的执行顺序就是从上到下依次执行,同一时间内只能执行一段代码。

JavaScript是单线程的,可是浏览器内部是多线程的,其异步也得靠其余线程来监听事件的响应,并将回调函数推入到任务队列等待执行。

单线程所作的就是执行栈中的同步任务,执行完毕后,再从任务队列中取出一个事件(没有事件的话,就等待事件),而后开始执行栈中相关的同步任务,不断的这样循环。

17.1 前端使用异步的场景

  • 定时任务 :setTimeout setInverval
  • 网络请求 :ajax请求,动态加载
  • 事件绑定
一、定时器
	 console.log(100)
	  setTimeout(function(){
	    console.log(200)
	  },1000)
	  console.log(300)
//100
//300
//200
	二、ajax请求
	  console.log('start')
	  $.get('test.json',function(data){
	    console.log(data)
	  })
	  console.log('end')
	三、动态<img>加载
	  console.log('start')
	  var img = document.createElement('img')
	  img.onload = function(){
	    console.log('load')
	
	  }
	  img.src='https://ss0.baidu.com/'
	  console.log('end')
//start
//end
//load
	四、事件绑定
	  console.log('start')
	  var btn1 = document.getElementById('btn1')
	  btn1.addEventListener('click',function () {
	    console.log('clicked')
	  })
	  console.log('end')
//start
//end
//click

复制代码

18.script标签的defer和async属性

  • async属性

表示后续文档的加载和渲染与js脚本的加载和执行是并行进行的,即异步执行。

  • defer属性

加载后续文档的过程和js脚本的加载(此时仅加载不执行)是并行进行的(异步),但js脚本的执行须要等到文档全部元素解析完成以后,DOMContentLoaded事件触发前执行。

区别   1.defer和async在网络加载过程是一致的,都是异步执行的;   2.二者的区别在于脚本加载完成以后什么时候执行,defer更符合大多数场景对应用脚本加载和执行的要求;   3.若是存在多个有defer属性的脚本,那么它们是按照加载顺序执行脚本的;而对于async,它的加载和执行是牢牢挨着的,不管声明顺序如何,只要加载完成就马上执行。

DOM

1.BOM与DOM区别与关联

1.1 BOM

  • BOM是Browser Object Model的缩写,即浏览器对象模型。
  • BOM没有相关标准。
  • BOM的最根本对象是window。 从1能够看出来:BOM和浏览器关系密切。浏览器的不少东西能够经过JavaScript控制的,例如打开新窗口、打开新选项卡(标签页)、关闭页面,把网页设为主页,或加入收藏夹,等等…这些涉及到的对象就是BOM。

从2能够看出来:因为没有标准,不一样的浏览器实现同一功能,能够须要不一样的实现方式,就要考虑浏览器兼容性了。

1.2 DOM

  • DOM是Document ObjectModel的缩写,即文档对象模型。
  • DOM是W3C的标准。
  • DOM最根本对象是document(其实是window.document)。

从1能够看出来:DOM和文档有关,这里的文档指的是网页,也就是HTML文档,和浏览器无关。

2.DOM事件模型

javascript中有两种事件模型:DOM0,DOM2。

2.1 DOM0级事件模型

分为两种

  • 行内事件:在标签中写事件
  • 元素.on事件名=函数

1.行内

<input type="button" id="btn" value="按钮" onclick="alert('hello world!')"> 
复制代码

2.元素.on事件名=函数

document.getElementById("btn").onclick = function () {
alert('hello world!');
} 
复制代码

注意,一个dom对象只能注册一个同类型的函数,注册多个同类型的函数的话,就会发生覆盖,以前注册的函数就会无效。

2.2 DOM2级事件模型

2.2.1 事件捕获和事件冒泡

事件冒泡:当一个元素上的事件被触发的时候,好比说鼠标点击了一个按钮,一样的事件将会在全部祖先元素中被触发。

事件捕获和事件冒泡机制以下图

此处输入图片的描述

2.2.2 DOM2级的注册事件和解除事件

在DOM2级中使用addEventListener()removeEventListener()来注册和解除事件(IE8及以前版本如下用attachEvent()添加事件和detachEvent()删除事件)。DOM2不会发生事件的覆盖,会依次的执行各个事件函数。   addEventListener('事件名称','回调','捕获(true)/冒泡(flase)')。示例以下:

<div id = 'outer' >
    <div id="inner" ></div>
</div>
<script>
    var click = document.getElementById('inner');
    var clickouter = document.getElementById('outer');
    click.addEventListener('click',function(event){
        alert('inner show');
        event.stopPropagation();
    },false);
    clickouter.addEventListener('click',function(){
        alert('outer show');
    },false);
</script>

复制代码

通常状况下,咱们在不添加stopPropagation()阻止冒泡函数时,点击inner,会先弹出inner,再弹出outer。添加了stopPropagation()函数以后,执行完inner的事件函数以后,就不会在执行outer的事件函数了

因为事件捕获阶段没有能够阻止事件的函数,因此通常都是设置为事件冒泡。

3. 事件委托

事件委托就是利用事件冒泡机制指定一个事件处理程序,来管理某一类型的全部事件。 即:利用冒泡的原理,把事件加到父级上,触发执行效果。 好处:

  • 只在内存中开辟了一处空间,节省资源同时减小了dom操做,提升性能
  • 动态添加的元素也绑定着事件。 例如,用ul中触发li来改变他们的背景颜色
<ul id='ul'>
    <li>111111</li>
    <li>222222</li>
    <li>333333</li>
 </ul>
 <button id='button'>添加元素</button>
 
 window.onload = function(){
      let oUl = document.getElementById('ul');
      let aLi = oUl.getElementsByTagName('li');
      let but = document.getElementById('button');
      let now = 3;
      oUl.onmouseover = function(e){
        let ev = e || window.event;
        let target = ev.target || ev.srcElement;
        if(target.nodeName.toLowerCase() == 'li'){
          target.style.background = 'red';
        }
      }
      oUl.onmouseout = function(e){
        let ev = e || window.event;
        let target = ev.target || ev.srcElement;
        if(target.nodeName.toLowerCase() == 'li'){
          target.style.background = '';
        }
      }
      but.onclick = function(){
        now ++;
        let newLi = document.createElement('li');
        newLi.innerHTML = 111111 * now;
        oUl.appendChild(newLi);
      }
    }
复制代码

WEB

1.HTTP 状态码

经常使用的状态码。 • 200表示服务端成功响应。 • 301表示永久重定向。 • 302表示临时重定向。 • 403表示请求被拒绝。 • 404表示服务端找不到请求的资源。 • 500表示处理请求出错。503表示服务不可用 ,504 表示网关超时。

2.HTTP缓存

2.1 HTTP报文

HTTP报文就是浏览器和服务器间通讯时发送及响应的数据块。 主要分为两部分 1.包含属性的首部(header)--------------------------附加信息(cookie,缓存信息等) 2.包含数据的主体部分(body)-----------------------HTTP请求真正想要传输的部分

2.2 HTTP缓存

http缓存能够理解为在服务端和客户端之间一个缓存数据库,你只须要设置一些参数便可实现,好比缓存/不缓存/时效内缓存/时效外缓存等(默认存在缓存)。缓存规则主要分为两类,即强制缓存和对比缓存。

2.2.1 强制缓存

对于强制缓存来讲,响应header中会有两个字段来标明失效规则Expires/Cache-Control

  1. Expires: HTTP 1.0的内容,做用基本忽略。
  2. Cache-Control Cache-Control 是最重要的规则。常见的取值有private、public、no-cache、max-age,no-store,默认为private。
  • private:客户端能够缓存
  • public: 客户端和代理服务器均可缓存
  • max-age=xxx:缓存的内容将在 xxx 秒后失效
  • no-cache:须要使用对比缓存来验证缓存数据(通常都设置为该值,使用缓存前都判断文件是否为最新,更为合理。)
  • no-store:全部内容都不会缓存,强制缓存,对比缓存都不会触发
2.2.2 对比缓存

对比缓存,顾名思义,须要进行比较判断是否可使用缓存。 可分为2种标识:

  1. Last-Modified / If-Modified-Since

Last-Modified:第一次请求时,服务器返回资源的最后修改时间; If-Modified-Since:再次请求时,浏览器通知服务器,上次请求时返回资源的最后修改时间。

若是Last-Modified小于等于If-Modified-Since,说明资源又被改动过,则响应整片资源内容,返回状态码200;不然,响应HTTP304,告知浏览器继续使用所保存的cache。

  1. Etag/If-None-Match(优先级高于Last-Modified/If-Modified-Since)

Etag:第一次请求时,服务器返回的资源惟一标识符(生成规则由服务器决定) If-None-Match:再次请求服务器时,浏览器通知服务器缓存数据的惟一标识。

若是Etag和If-None-Match不一样,说明资源又被改动过,则响应整片资源内容,返回状态码200;不然,响应HTTP304,告知浏览器继续使用所保存的cache。

浏览器第一次请求:

此处输入图片的描述
浏览器再次请求:
此处输入图片的描述

总之,对于强制缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行比较缓存策略。 对于比较缓存,将缓存信息中的Etag和Last-Modified经过请求发送给服务器,由服务器校验,返回304状态码时,浏览器直接使用缓存。

3.http缓存方案

3.1 md5/hash缓存

经过不缓存html,为静态文件添加MD5或者hash标识,解决浏览器没法跳过缓存过时时间主动感知文件变化的问题

webpack提供了webpack-md5-hash插件,能够帮助咱们在项目发布时自动修改文件标识。

3.2 CDN缓存

CDN缓存提供了分流以及访问加速等优点条件,是能够经过登陆,手动更新CDN缓存的,变相解决了浏览器缓存没法手动控制的问题。

3.3 浏览器操做对HTTP缓存的影响

此处输入图片的描述

4.从URL到页面显示的过程

浏览器在获得用户请求以后,经历了下面这些阶段:重定向→拉取缓存→DNS查询→创建TCP连接→发起请求→接收响应→处理HTML元素→元素加载完成

一、首先,在浏览器地址栏中输入url

二、浏览器先查看浏览器缓存-系统缓存-路由器缓存,若是缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操做。

三、域名解析(DNS解析),解析获取相应的IP地址。

四、浏览器经过三次握手与远程Web服务端来创建一个TCP/IP链接

五、握手成功后,浏览器向服务器发送http请求,请求数据包。

六、服务器处理收到的请求,将数据返回至浏览器。

七、浏览器进行HTML加载,加载完后开始解析

八、其余资源下载:html解析遇到外部资源,如css\js\图片,会启用其余线程下载资源。注意,当遇到的js文件,html解析会停下来,直到js文件下载并执行完后,从新开始html的解析工做。

九、Dom树构建:在html解析同时,解析器会把解析完的html 转化为DOM对象,再进一步构建出DOM 树。

十、CSSOM树构建:当CSS下载完,解析器对css进行并生产css对象,进一步构建成CSSOM树。

十一、渲染树:DOM树和CSSO树构建完成后,浏览器就会根据这两棵树构建一颗渲染树。

十二、布局计算:渲染树构建完成之后,全部元素的位置关系和应用样式就肯定了,这是浏览器会计算全部元素的大小和绝对位置。

1三、渲染:布局计算完成后,浏览器就能够在页面上渲染元素。通过渲染引擎的处理后,整个页面就显示在屏幕上。

5.web会话跟踪的方法

HTTP是一种无状态的协议,为了分辨连接是谁发起的,需本身去解决这个问题。否则有些状况下即便是同一个网站每打开一个页面也都要登陆一下

5.1 Cookie

Cookies是服务器在本地机器上存储的小段文本,即访问后网站的相关信息,它随每个请求发送至同一服务器,是在客户端保持状态的方案。 Cookie的主要内容包括:名字,值,过时时间,路径和域 ,数据大小不能超过4k。

5.2 sessionStorage 和 localStorage

与cookie相似,但不会自动把数据发给服务器,仅在本地保存,数据大小可达5M或以上。

• localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
• sessionStorage 数据在当前浏览器窗口关闭后自动删除。
复制代码

5.3 URL重写

就是首先得到一个进入的URL请求而后把它从新写成网站能够处理的另外一个URL的过程。

5.4 隐藏input

隐藏域在页面中对于用户是不可见的,在表单中插入隐藏域的目的在于收集或发送信息,以利于被处理表单的程序所使用。浏览者单击发送按钮发送表单的时候,隐藏域的信息也被一块儿发送到服务器。

6.GET 和 POST 的区别

GET和POST是HTTP协议中发送请求的两种方法,它们的区别,简单的说: GET产生一个TCP数据包;POST产生两个TCP数据包。

也就是说:对于GET方式的请求,浏览器会把http的header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

  1. GET与POST都有本身的语义,不能随便混用。
  2. 据研究,在网络环境好的状况下,发一次包的时间和发两次包的时间差异基本能够无视。而在网络环境差的状况下,两次包的TCP在验证数据包完整性上,有很是大的优势。
  3. 并非全部浏览器都会在POST中发送两次包,Firefox就只发送一次。

具体差别可表现如下5个方面:

  • 缓存上,GET请求会被浏览器主动cache,而POST不会,除非手动设置。
  • 编码方式上,GET请求只能进行url编码,而POST支持多种编码方式。
  • 参数长度上,GET请求在URL中传送的参数是有长度限制的,而POST没有。
  • 参数的数据类型上,GET只接受ASCII字符,而POST没有限制。
  • 参数传递上,GET参数经过URL传递,POST放在Request body中,更安全。

6.网站性能优化

可分为三个方面,网络传输性能、页面渲染性能以及JS阻塞性能

6.1 网络传输性能优化

6.1.1浏览器缓存:在服务器上设置的Etag字段。

在浏览器接收到服务器响应后,会检测响应头部(Header),若是有Etag字段,那么浏览器就会将本次缓存写入硬盘中。 注意,在构建阶段,须要为咱们的静态资源添加md5 hash后缀,避免资源更新而引发的先后端文件没法同步的问题。

6.1.2资源打包压缩:用webpack进行自动化打包编译

对webpack进行上线配置时,咱们要特别注意如下几点:

  1. JS压缩: new webpack.optimize.UglifyJsPlugin()
  2. HTML压缩:
  • 使用html-webpack-plugin自动化注入JSCSS打包HTML文件
  • 书写HTML元素的src 或 href 属性时,能够省略协议部分
  1. 提取公共资源: new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'scripts/common/vendor-[hash:5].js' })
  2. 提取css并压缩 extract-text-webpack-plugin
  3. 服务器上开启Gzip传输压缩,但注意,不要对图片文件进行Gzip压缩
6.1.3图片资源优化

1.不要在HTML里缩放图像 2.使用雪碧图(CSS Sprite) 自动化生成雪碧图的工具 3.使用字体图标(iconfont); 4.使用WebP 是能够加快图片加载速度的图片格式,叉拍云 5.使用cdn 同时使用DNS预解析技术DNS Prefetch

6.2页面渲染性能优化

主要是下降重排和重绘的频率和成本

1.CSS属性读写分离

2.经过切换class或者使用元素的style.csstext属性去批量操做元素样式。

3.DOM元素离线更新 例如display:none对元素隐藏,在元素“消失”后进行相关操做。

4.将没用的元素设为不可见:visibility: hidden

5.压缩DOM的深度 一个渲染层内不要有过深的子元素,少用DOM完成页面样式,多使用伪元素或者box-shadow取代。

6.图片在渲染前指定大小 由于img元素是内联元素,因此在加载图片后会改变宽高,严重的状况会致使整个页面重排,因此最好在渲染前就指定其大小,或者让其脱离文档流。

6.3 js阻塞性能

在编程的过程当中,若是咱们使用了闭包后未将相关资源加以释放,或者引用了外链后未将其置空(好比给某DOM元素绑定了事件回调,后来却remove了该元素),都会形成内存泄漏的状况发生,进而大量占用用户的CPU,形成卡顿或死机。咱们可使用chrome提供的JavaScript Profile进行测试。

7.浏览器的渲染机制

CSS

1.CSS盒模型

HTML元素的显示呈现为一个矩形,CSS标准中称之为Box。一个HTML元素占据空间的大小由盒模型决定。在盒模型中,一个盒子由内容content、内边距padding、边框border和外边距margin共同构成,其尺寸也是这四部分的尺寸之和。 盒模型是有两种标准: • 标准模型--盒模型的宽高只是内容(content)的宽高, • IE模型中--盒模型的宽高是内容(content)+填充(padding)+边框(border)的总宽高。

2.css reset 和 normalize.css 有什么区别?

Normalize.css只是一个很小的css文件,它在HTML元素样式上提供了跨浏览器的高度一致性。相比于传统的CSS reset,Normalize.css是一种现代的、为HTML5准备的优质替代方案。 Normalize vs Reset

  • Normalize.css 保护了有价值的默认值

Reset经过为几乎全部的元素施加默认样式,强行使得元素有相同的视觉效果。相比之下,Normalize.css保持了许多磨人的浏览器样式。这就意味着你不用再为全部公共的排版元素从新设置样式。当一个元素在不一样的浏览器中有不一样的默认值时,Normalize.css会力求让这些样式保持一致并尽量与现代标准符合。

  • Normalize.css 修复了浏览器的bug

它修复了常见的桌面端与移动端浏览器的bug。这每每超出了Reset所能作到的范围。关于这一点,Normalize.css修复的问题包含了HTML5元素的显示设置、预格式化文字的font-size问题、在IE9中SVG的溢出、许多出如今各浏览器和操做系统中的与表单相关的bug。

  • Normalize.css 不会让你的调试工具变的杂乱

使用Reset最让人困扰的地方莫过于在浏览器调试工具中大段大段的继承链,在Normalize.css中就不会有这样的问题。

  • Normalize.css 是模块化的

这个项目已经被拆分为多个相关却又独立的部分,这使得你可以很容易也很清楚地知道哪些元素被设置了特定的值。所以这能让你本身选择性地移除掉某些永远不会用到的部分(好比表单的通常化)。

  • Normalize.css 拥有详细的文档

3.BFC

3.1 定义:

BFC 全称为 block formatting context,中文为“块级格式化上下文” 若是一个元素具备 BFC,内部子元素再怎么翻江倒海、翻 云覆雨,都不会影响外部的元素。

3.2 触发 BFC 常见的状况以下:

  • 根元素;
  • float 的值不为 none;
  • overflow 的值为 auto、 scroll 或 hidden;
  • display 的值为 table-cell、 table-caption 和 inline-block 中的任何一个;
  • position 的值不为 relative 和 static。

3.3 用途:

  • BFC 元素是不会发生 margin 重叠的;
  • BFC 元素能够用来清除浮动的影响: .lbf-content { overflow: hidden; } /* IE7+ */
  • 实现自适应布局 普通流体元素在设置了 overflow:hidden 后,会自动填满容器中除了浮动元素之外的剩余空间,造成自适应布局效果.
    此处输入图片的描述

4.居中

4.1 行内元素

  1. 父元素设置text-align: center;(只设置水平居中) 优势:是不用计算子元素尺寸。

  2. 子元素经过absolute配合transform()(一样适用于块级元素)

.child{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
复制代码

此处输入图片的描述
优势:不用计算当前元素尺寸。 3. 子元素直接使用 absolute(一样适用于块级元素)

.child{
    width: 100px;
    height: 100px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -50px; /*高度的一半*/
    margin-left: -50px; /*宽度的一半*/
  }
复制代码

注意,须要计算子元素宽高. 4. 父元素使用flex布局(一样适用于块级元素)

//方案一:配合使用 justify-content和 align-items属性
.father{
    display: flex;
    justify-content: center; /*水平居中*/
    align-items: center; /*垂直居中*/
  }
  //方案二:子元素只用margin属性,若是浏览器不兼容flex属性,有回退做用
  .father{
    display: flex;
  }
  .child{
    margin: auto;
  }
复制代码

4.2 块级元素

  1. 使用margin:0 auto配合元素的width
#center{
    width: 100px;
    margin: 0 auto;
}

复制代码

注意,当元素处于position:absolute;时,margin:0 auto无效,须要将right于left都设为0才能够,以下所示

#center{
    width: 100px;
    margin: 0 auto;
    position:absolute;
    right:0;
    left:0;
}

复制代码

法2.3.4.同上

4.3 垂直居中

  1. 经过line-height
#main{
    height: 200px;
    line-height: 200px;
}

复制代码

缺点:须要固定父元素的height值,而且居中元素若是是多行文本将错乱。仅适合小元素,单行文本。

法2.3.4.同上。

5.清除浮动

两大基本方法

  • 元素添加伪类
.clearfix:after{content:'';display:table;clear:both} //ie8+
.clearfix{*zoom:1;}
复制代码

2.父元素BFC

.lbf-content { overflow: hidden; }//IE7+
复制代码

6.css优先级计算规则

6.1 选择器类型

  • id选择器(#myid)、
  • 类选择器(.myclassname)、属性选择器(a[rel=”external”])、伪类选择器(a:hover, li:nth-child)
  • 标签选择器(h1)、伪元素(::before)
  • 相邻选择器(h1 + p)、
  • 子选择器(ul > li)、
  • 后代选择器(li a)、
  • 通配符选择器(*)、

6.2 优先级

ID选择器 > 类选择器|属性选择器|伪类 > 标签|伪元素 > 通配符

css规则由选择器和声明块组成:

此处输入图片的描述

css优先级就是经过选择器的特殊值计算的,选择器的特殊性值表述为4个部分,用0,0,0,0表示:

  • ID选择器的特殊性值,加0,1,0,0。
  • 类选择器、属性选择器或伪类,加0,0,1,0。
  • 标签和伪元素,加0,0,0,1。
  • 通配选择器*对特殊性没有贡献,即0,0,0,0。
  • 最后比较特殊的一个标志!important(权重),它没有特殊性值,但它的优先级是最高的,能够认为它的特殊性值为1,0,0,0,0。
a{color: yellow;} /*特殊性值:0,0,0,1*/
div a{color: green;} /*特殊性值:0,0,0,2*/
.demo a{color: black;} /*特殊性值:0,0,1,1*/
.demo input[type="text"]{color: blue;} /*特殊性值:0,0,2,1*/
.demo *[type="text"]{color: grey;} /*特殊性值:0,0,2,0*/
#demo a{color: orange;} /*特殊性值:0,1,0,1*/
div#demo a{color: red;} /*特殊性值:0,1,0,2*/
复制代码

选择器特殊性值是从左向右排序的,也就是1,0,0,0大于以0开头的全部特殊性值,行间样式的特殊性是1,0,0,0,比ID选择器优先级高。

6.3 层叠

假如特殊性相同的两条规则应用到同一个元素,css会先查看规则的权重(!important),加了权重的优先级最高;当权重相同的时候,css规则会按顺序排序,后声明的规则优先级高。

例如,伪类,:link、:visited、:hover、:active,都遵循“爱恨原则LVHA”(LoVe HAte),特殊性值相同,后声明的规则优先级高,就能够覆盖前面的。

7.gif/png/jpge

HTML

1. 标签分类

• 文档元信息:一般是出如今head标签种,包含了描述文档自身的一些信息,诸如 title、meta、style、link、base ; • 语义相关:扩展了纯文本,表达文章结构、不一样语言要素的标签,诸如 section、nav 的标签; • 连接:提供到文档内和文档外的的连接; • 替换型标签:引入声音、图片、视频等外部元素替换自身的一类标签; • 表单:用于填写和提交信息的一类标签; • 表格:表头、表尾、单元格等表格的结构。

2.HTML 语义化

语义化标签是纯文本的补充,好比标题,天然段,章节等,这些内容是纯文字没法表达的,咱们就须要语义标签表达.

正确使用优势以下: • 便于团队维护和开发 • 去掉css样式后网页结构完整 • 便于阅读机器阅读,适合搜索引擎检索seo

相反,错误地使用语义标签,会给机器阅读形成混淆、增长嵌套,给 Css编写加剧负担。 但现代互联网产品里,HTML用于描述“软件界面”多过于“富文本",而软件界面里的东西,实际上几乎是没有语义的。好比说,咱们作了一个购物车功能,必定要用给商品套上ul吗?好比,加入购物车的按钮,必定要用button吗?

实际上,我认为是不必,由于这个场景里,跟文本的列表以及表单的button,已经相差很远了。因此,在软件界面,能够直接用div和span。

3.meta viewport 是作什么用的,怎么写?

在移动浏览器中使用viewport元标签控制布局,包含如下内容:

<meta name="viewport" content="with=device-with,initial-scale=1,maximum-scale=1">
复制代码

4.html5为何只须要写<!DOCTYPE>

HTML5不基于SGML,所以不须要对DTD进行引用,可是须要doctype来规范浏览器的行为 因此,html5只有一种:<!DOCTYPE> 可是html4.01有三种,分别是strict、transitional、frameset。

5.html5新特性、移除元素,HTML5新标签的浏览器兼容

实现上:h5再也不是SGML的子集。 一、新特性:主要是关于图像,位置,存储,多任务等功能的增长,如: • 绘画canvas • 用于媒介回放的video和audio元素 • 本地离线存储localStorage,长期存储,浏览器关闭以后数据不丢失 sessionStorage的数据在浏览器关闭后自动删除 • 语意化更好的内容元素,好比 article、footer、header、nav、section • 表单控件,calendar、date、time、email、url、search; • 新的技术webworker, websocket, Geolocation; 二、移除的元素: 纯表现的元素:basefont,big,center,font, s,strike,tt,u; 对可用性产生负面影响的元素:frame,frameset,noframes; 三、处理兼容性: • IE8/IE7/IE6支持经过document.createElement方法产生的标签,能够利用这一特性让这些浏览器支持HTML5新标签,浏览器支持新标签后,还须要添加标签默认的样式。 • 使用html5shim,可让IE9或更低版本能支持html5 <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>

6.行内元素、块级元素、空(void)元素

• 行内元素有:a,b,span,img(我曾觉得是block),input,strong,select
• 块级元素有:div、ul(无序)、ol(有序)、li、p等
• 空元素:<br><hr><link><script>
空元素定义:html元素的内容就是其两个标签之间的content,因此,标签之间没有内容的就是空元素
复制代码

7.页面导入样式时,使用link@import的区别

写法上:

<link rel="stylesheet" href="路径" />
<style type="text/css">
    @import '路径'
</style>
复制代码

本质上:link属于XHTML标签,除了加载css以外,还能定义RSS,定义rel链接属性等做用。而@import是css提供的,只能用于加载css; 解析上:link是跟着页面加载同时加载的,可是@import会等到页面加载完再加载 兼容上:@import IE5以上才能识别,link无限制

相关文章
相关标签/搜索