喋喋不休

真正的勇士,胖还贪吃,困还熬夜,穷还追星,丑还颜控

0%

call,apply,bind

在JavaScript中,call、apply和bind是Function对象自带的三个方法,都是为了改变函数体内部 this 的指向。

apply 、 call 、bind 三者第一个参数都是 this 要指向的对象,也就是想指定的上下文;

apply 、 call 、bind 三者都可以利用后续参数传参;

bind 是返回对应 函数,便于稍后调用;apply 、call 则是立即调用 。

1.列子:

function sayHello() {}

sayHello.prototype = {
    name: 'jack',
    say: function () {
        console.log('Hello ' + this.name);
    }
}

var people = new sayHello(); // 此时方法里面的this指的是sayHello
people.say(); // Hello jack

但是如果我们有一个对象 child= {name : ‘lucy’} ,我们不想重新定义 say 方法,那么我们可以通过 call 或 apply 用 apple 的 say 方法:

child = {
    name : 'lucy'
}
people.say.call(child); //此时的this的指向已经同过call()方法改变了,指向的是child,this.name就是child.name='lucy';
//结果是Hello lucy 

people.say.apply(child);//同理,此时的this的指向已经同过apply()方法改变了,指向的是child,this.name就是child.name ='lucy';
//Hello lucy

// 如果传入的是 null:
people.say.apply(null); // null是window下的,此时,this 就指向了window ,但是window下并没有name这个属性,因此this.name就是window.name=undefined;
//Hello undefined

2.对于 apply、call 二者而言,作用完全一样,只是接受 参数 的方式不太一样。call 是把参数按顺序传递进去,而 apply 则是把参数放在数组 里。

var array1 = [12,'foo',{name:'Joe'},-2458];
var array2 = ['Doe' , 555 , 100];

Array.prototype.push.call(array1, array2);
// 这里用 call 第二个参数不会把 array2 当成一个数组,而是一个元素

//等价于array1.push(‘‘'Doe' , 555 , 100’’);
//array1.length=5;

Array.prototype.push.apply(array1, array2); // 这里用 apply 第二个参数是一个数组

// 等价于:  array1.push('Doe' , 555 , 100);
//array1.length=7;

3.类(伪)数组使用数组方法

var divElements = document.getElementsByTagName('div'); //虽然 divElements 有length属性,
但是他是一个伪数组,不能使用数组里面的方法

Array.isArray(divElements);// false

var domNodes = Array.prototype.slice.call(document.getElementsByTagName('div'));
// 将数组对象Array里的this指向伪数组document.getElementsByTagName('div'), 
//slice() 方法可从已有的数组中返回选定的元素,不传参数是,返回整个数组 

Array.isArray(domNodes);// true

4. 验证一个对象的类型可以用:

Object.prototype.toString.call(obj) 

5.bind() 方法,MDN 的解释是:bind() 方法会创建一个 新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind() 方法的第一个参数 作为 this,传入 bind() 方法的 第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。

var bar = function(){
    console.log(this.x);
}
var foo = {
    x:3
}

bar(); // undefined
var func = bar.bind(foo); //此时this已经指向了foo,但是用bind()方法并不会立即执行,而是创建一个新函数,如果要直接调用的话 可以 bar.bind(foo)()


func(); // 3

6.在 Javascript 中,多次 bind() 是无效的。

var fun1 = function(){
    console.log(this.x);
}
var fun2 = {
    x:3
}
var fun3 = {
    x:4
}
var func = fun1.bind(fun2).bind(fun3);
func(); //3

var fun4 = {
    x:5
}

var func = fun1.bind(fun2).bind(fun3).bind(fun4);
func(); //3

7.apply、call、bind 三者相比较,之间又有什么异同呢?何时使用 apply、call,何时使用 bind 呢。简单的一个例子:

var obj = {
    name: ‘marry’,
};

var foo = {
    getNmae: function() {
        return this.name;
    }
}
console.log(foo.getNmae.bind(obj)());  //marry
console.log(foo.getNmae.call(obj));    //marry
console.log(foo.getNmae.apply(obj));   //marry

bind只是返回对应的函数,还需要调用才行

闭包之前我们来看看函数的作用域以及作用域链

函数的生命周期:

1、程序开始执行:
创建一个Execution Context Stack(ECS)
依次保存正在调用的函数的执行环境的栈结构
创建全局作用域对象:window
在ECS中压入第一个全局执行环境EC,全局EC引用window

node

2、定义函数时:
创建函数对象,封装函数的定义
在函数对象中,设置scope属性,引用函数来自的作用域,通常scope都是window
用函数名创建全局变量,引用函数对象

node

3、调用函数时:
创建一个活动对象Actived Object(AO): 活动对象:保存函数的局部变量的函数作用域对象。
向ECS中压入本次函数调用的执行环境EC
EC引用AO
设置AO引用函数的scope(window)

node

4、函数调用后:
EC出栈,导致AO无人使用,被释放
导致,AO中的局部变量一同被释放!

node

作用域: 一个变量的可用范围
其实window对象就是全局作用域
AO对象就是函数作用域
AO对象又引用了window对象

作用域链: 由各级作用域对象,逐级引用形成的链式结构,就是作用域链。
作用域链的末尾是window对象
作用域链控制着变量的使用顺序:
优先使用AO中的局部变量
如果AO中没有,就延作用域链向下找。
如果到window还没找到,就报错

什么是闭包?

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

MDN 上面这么说:闭包是一种特殊的对象。
它由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。

为什么使用:

全局变量: 优: 随处可用,可反复使用
          缺: 易被全局污染

局部变量: 优: 仅在函数内可用,不会被污染
          缺: 无法反复使用

何时使用: 如果希望重用一个变量,且不希望该变量被随意篡改时。

如何实现: 3步

1. 用外层函数将受保护的变量和操作变量的函数封装在内部

2. 外层函数将内层函数返回

3. 调用外层函数,获得返回的内层函数对象。

说明: 1. 两次外层函数调用返回的闭包中,受保护的变量是各自独立的,没有任何关系。

创建闭包

1.开始几步和函数的声明创建一样

node

2.函数创建完成后的各自引用

node

3.调用外层函数形成活动AO,向全局EC中压入本次函数的EC

node

4.外层函数返回内层函数,形成内层函数的对象,这样图中绿色的箭头形成引用

node

5.当外层函数的调用结束后,外层函数的作用域并没有释放,留了下来,就形成了大名鼎鼎的bibox

node

6.调用执行函数时,n++

node

7.函数调用结束后,getNum出栈

node

8.当执行n=1时,并没有改变outer AO中的局部变量,所以最后的调用n=2

node

function outer(){
    var n = 1;
    return function(){
        console.log(n++)
    }
}
var getNum = outer();
getNum();   //1
n = 1; 
getNum()  //2

闭包缺点:

占用更多内存空间

且一旦形成闭包,无法自动释放。

至此,闭包的全部解析就这样了

过程概述

1. 浏览器查找域名对应的 IP 地址;

2. 浏览器根据 IP 地址与服务器建立 socket 连接;

3. 浏览器与服务器通信: 浏览器请求,服务器处理请求;

4. 浏览器与服务器断开连接。

根据域名查找 IP 地址

概念

IP 地址:IP 协议为互联网上的每一个网络和每一台主机分配的一个逻辑地址。
IP 地址如同门牌号码,通过 IP 地址才能确定一台主机位置。
服务器本质也是一台主机,想要访问某个服务器,必须先知道它的 IP 地址;

域名( DN ):IP 地址由四个数字组成,中间用点号连接,在使用过程中难记忆且易输入错误,
所以用我们熟悉的字母和数字组合来代替纯数字的 IP 地址,
比如我们只会记住 www.baidu.com(百度域名) 而不是 220.181.112.244(百度的其中一个 IP 地址);

DNS: 每个域名都对应一个或多个提供相同服务服务器的 IP 地址,只有知道服务器 IP 地址才能建立连接,
所以需要通过 DNS 把域名解析成一个 IP 地址。

查找过程

1、浏览器搜索自己的 DNS 缓存(维护一张域名与 IP 地址的对应表);

2、搜索操作系统中的 DNS 缓存(维护一张域名与 IP 地址的对应表);

3、搜索操作系统的 hosts 文件( Windows 环境下,维护一张域名与 IP 地址的对应表);

4、操作系统将域名发送至 LDNS(本地区域名服务器,如果你在学校接入互联网,则 LDNS 服务器就在学校,
如果通过电信接入互联网,则 LDNS 服务器就在你当地的电信那里。)LDNS 查询 自己的 DNS 缓存
(一般查找成功率在 80% 左右),
查找成功则返回结果,失败则发起一个迭代 DNS 解析请求;

    1、LDNS 向 Root Name Server (根域名服务器,其虽然没有每个域名的的具体信息,
    但存储了负责每个域,如 com、net、org等的解析的顶级域名服务器的地址)发起请求,此处,Root Name 

    2、Server 返回 com 域的顶级域名服务器的地址;

    3、LDNS 向 com 域的顶级域名服务器发起请求,返回 baidu.com 域名服务器地址;

    4、LDNS 向 baidu.com 域名服务器发起请求,得到 www.baidu.com 的 IP 地址;

5、LDNS 将得到的 IP 地址返回给操作系统,同时自己也将 IP 地址缓存起来;

6、操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起来;

7、至此,浏览器已经得到了域名对应的 IP 地址。

补充说明

  • 域名与 URL 是两个概念:域名是一台或一组服务器的名称,用来确定服务器在 Internet 上的位置;URL 是统一资源定位符,用来确定某一个文件的具体位置

  • IP 地址与域名不是一一对应的关系:可以把多个提供相同服务的服务器 IP 设置为同一个域名,但在同一时刻一个域名只能解析出一个 IP地址;同时,一个 IP 地址可以绑定多个域名,数量不限;

建立连接–三次握手

1、主机向服务器发送一个建立连接的请求(您好,我想认识您);

2、服务器接到请求后发送同意连接的信号(好的,很高兴认识您);

3、主机接到同意连接的信号后,再次向服务器发送了确认信号(我也很高兴认识您),
   自此,主机与服务器两者建立了连接。

补充说明

  • TCP 协议:三次握手的过程采用 TCP 协议,其可以保证信息传输的可靠性,三次握手过程中,若一方收不到确认信号,协议会要求重新发送信号。

网页请求与显示

当服务器与主机建立了连接之后,下面主机便与服务器进行通信。网页请求是一个单向请求的过程,即是一个主机向服务器请求数据,服务器返回相应的数据的过程。

1、浏览器根据 URL 内容生成 HTTP 请求,请求中包含请求文件的位置、请求文件的方式等等;

2、服务器接到请求后,会根据 HTTP 请求中的内容来决定如何获取相应的 HTML 文件;

3、服务器将得到的 HTML 文件发送给浏览器;

4、在浏览器还没有完全接收 HTML 文件时便开始渲染、显示网页;

5、在执行 HTML 中代码时,根据需要,浏览器会继续请求图片、CSS、JavsScript等文件,过程同请求 HTML ;

断开连接–四次挥手

1、主机向服务器发送一个断开连接的请求(不早了,我该走了);

2、服务器接到请求后发送确认收到请求的信号(知道了);

3、服务器向主机发送断开通知(我也该走了);

4、主机接到断开通知后断开连接并反馈一个确认信号(嗯,好的),服务器收到确认信号后断开连接;

补充说明

  • 为什么服务器在接到断开请求时不立即同意断开:当服务器收到断开连接的请求时,可能仍然有数据未发送完毕,所有服务器先发送确认信号,等所有数据发送完毕后再同意断开。

  • 第四次握手后,主机发送确认信号后并没有立即断开连接,而是等待了 2 个报文传送周期,原因是:如果第四次握手的确认信息丢失,服务器将会重新发送第三次握手的断开连接的信号,而服务器发觉丢包与重新发送的断开连接到达主机的时间正好为 2 个报文传输周期。

一.html 和 css

浏览器分类

浏览器:IE,Chrome,FireFox,Safari,Opera。

内核:Trident,Gecko,Presto,Webkit。

行内元素和块级元素

行内元素:水平排列,不能包含块级页面;width/height无效,margin/padding无效

块级元素:各占据一行,垂直方向排列。从新行开始结束接着一个断行。

兼 容 性:display:inline-block;display:inline;zoom:1;

清除浮动有哪些方式?比较好的方式是哪一种?

1) 浮动的意义:初衷是用于让文字环绕图片,float可以自动包裹元素,float可导致高度坍塌–
当标签里元素只有样子没有实际高度时会坍塌,浮动会脱离文档流,产生自己的块级上下文。

1) 本级尾部加标签:结尾处加空标签(div,br…)并clear :both;
2) 本级定义父级
伪类:after和zoom
高度:height
overflow:hidden/auto
display:table
浮动并定义宽度
比较好的是第3种方式,简洁方便。

box-sizing常用的属性

属性:box-sizing: content-box|border-box|inherit;

作用:

1.content-box:宽高度分别对应到元素的content,内边距和边框在宽高之外渲染(默认)。
2.border-box:宽高度分别对应到元素的border,任何内边距和边框都将在已设定的宽高内渲染。

Doctype作用,标准模式与兼容模式

告知浏览器的解析器用什么文档标准解析这个文档。
DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。

标准模式的渲染引擎都是以该浏览器支持的最高标准运行。
在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。

HTML5 为什么只需要写 < Doctype html>?

如果浏览器基于SGML,需要对DTD引用;H5不基于它,HTML4.01基于它doctype用于规范浏览器行为,H5需要引入它以受控

页面导入样式时,使用link和@import有什么区别?

1.语法的角度:

link属于XHTML标签,除了加载CSS外,还能用于定义RSS, 定义rel连接属性等作用;
而@import是CSS提供的语法,只能用于加载CSS;

2.浏览器解析的角度

页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载(标准浏览器);

3.兼容性问题

import是CSS2.1 提出的,只在IE5以上才能被识别,而link是XHTML标签,无兼容问题。

总之,link要优于@import,由此决定了它的适应性更广,加载性更快,兼容性更强。

html5 vs html4.01

HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。

  • 绘画 :canvas,svg;
  • 媒体元素: video 和 audio 元素;
  • 存储:本地离线存储 localStorage ,sessionStorage 的数据在浏览器关闭后自动删除;
  • 语义化标签:article、footer、header、nav、section,main,aside;
  • 表单控件:calendar、date、time、email、url、search,upload;
  • 新的技术webworker, websocket, Geolocation;
  • hack:IE8/IE7/IE6支持通过document.createElement方法产生的标签, 可以利用这一特性让这些浏览器支持HTML5新标签,
    浏览器支持新标签后,还需要添加标签默认的样式。 也可以直接使用成熟的框架、比如html5shim,

语义化标签的理解:用正确的标签做正确的事情。

  • 语义化:html语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析;
  • 利于SEO:即使在没有样式CSS情况下也以一种文档格式显示,并且是容易阅读的;
    搜索引擎的爬虫也依赖于HTML标记来确定上下文和各个关键字的权重;
    离线储存
方式 数据源 信息量 接口 存储空间独立性
cookie B+S 依赖
sessionStorage B 独立
localStorage B 独立

盒模型

  • 分类:标准盒模型和IE盒模型;区别:content 是否包含 border 和 pading(IE包含);

    盒模型: content,padding,margin ,border

CSS 选择符及继承性和优先级算法,伪类

选择器

1.id选择器( # myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p)
4.相邻选择器(h1 + p)
5.子选择器(ul > li)
6.后代选择器(li a)
7.通配符选择器( * )
8.属性选择器(a[rel = "external"])
9.伪类选择器(a: hover, li: nth - child)

可继承性

* 可继承属性
font-size font-family color,ul,li,dd,dt;
* 不可继承的属性
border padding margin width height
优先级

就近原则:同权重情况下样式定义最近者为准,载入样式以最后载入的定位为准;
优先级算法: !important > id > class > tag

CSS3新增伪类

p:first-of-type 选择属于其父元素的首个 <p> 元素的每个 <p> 元素。
p:last-of-type 选择属于其父元素的最后 <p> 元素的每个 <p> 元素。
p:only-of-type 选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。
p:only-child 选择属于其父元素的唯一子元素的每个 <p> 元素。
p:nth-child(2) 选择属于其父元素的第二个子元素的每个 <p> 元素。
:enabled :disabled 控制表单控件的禁用状态。
:checked 单选框或复选框被选中。

居中显示问题

  • 水平居中div{width:200px; margin:0 auto; }
  • 垂直居中div{ background: red; width: 100px; height: 200px; position: absolute; top: 50%; left: 50%; margin-left: -50px; margin-top: -100px; /transform: translate(-50%,-50%);/ }

display vs position

display:block|inline-block|list-item|none

position:
absolute :生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。
fixed :(老IE不支持)生成绝对定位的元素,相对于浏览器窗口进行定位。
relative:生成相对定位的元素,相对于其正常位置进行定位。
static :默认值。没有定位,元素出现在正常的流中, (忽略 top, bottom, left, right z-index 声明)
inherit: 规定从父元素继承 position 属性的值。

CSS3新特性

  • CSS3实现圆角(border-radius:8px),
  • 阴影(box-shadow:10px),
  • 对文字加特效(text-shadow、)
  • 线性渐变(gradient)
  • 旋转(transform)
  • ransform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px)
  • skew(-9deg,0deg);//旋转,缩放,定位,倾斜
  • 增加了更多的CSS选择器 多背景 rgba

二 JavaScript

事件代理/事件委托(delegation)

当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件
委托给父节点来触发处理函数。这主要得益于浏览器的事件冒泡机制。

function(client, clientMethod) {
return function() { return clientMethod.apply(client, arguments); } } var agentMethod = delegate (client, clientMethod); agentMethod();
简单实例
var resources = document.querySelector(‘#resources’),
log = document.querySelector(‘#log’);
resources.addEventListener(‘mouseover’, showtarget, false);
function showtarget(ev) { var target = ev.target; if (target.tagName === ‘A’) { log.innerHTML = ‘A link, with the href:’ + target.href; }
if (target.tagName === ‘LI’) { log.innerHTML = ‘A list item’; }
if (target.tagName === ‘UL’) { log.innerHTML = ‘The list itself’; }} //方便之处 document.getElementById(“parent-list”).addEventListener(“click”, function(e) { if(e.target && e.target.nodeName == “LI”) { console.log(“List item “, e.target.id.replace(“post-“), “ was clicked!”); } });

this对象使用场景

  • 作为函数调用,this 绑定全局对象,浏览器环境全局对象为 window 。
  • 内部函数的 this 也绑定全局对象(应该绑定到其外层函数对应的对象上,这是 JavaScript的缺陷,用that替换)
  • 作为构造函数使用,this 绑定到新创建的对象。
  • 作为对象方法使用,this 绑定到该对象。
  • 使用apply或call调用 this 将会被显式设置为函数调用的第一个参数。

原型继承原理

每个函数都有一个原型对象的属性(F.prototype),每个函数都可以是一个构造函数。
即通过new关键字可以创建任意函数的一个实例。
原型继承原理:JS中是没有类的,所有继承属于基于原型的继承。在调用某个对象的属性或方法
时,js引擎会优先在该对象自身上查找该属性或方法,如果没有便去该对象的构造函数中去查找,
如此逐级递归查找,直到原型链的最顶层

hash表

哈希表是根据key-value键值对而直接访问对象在内存的存储位置的数据结构。即,它是
通过把键值通过一个函数计算,映射到表中的一个位置来访问记录,这加快了查找速度。这个映射
称为散列函数,存放记录的数组为散列表。
null和undefined
undefined:js数据类型之一,undeclared是js的一种语法错误类型。

JS宿主对象和原生对象

  • 宿主对象:COM=DOM and BOM ,C++写的对象;
  • 原生对象:Object,Function,Array,String,Boolean,Number
    Date,RegExp,Error,Math,Promise等。

eval

把对应的字符串解析成JS代码并运行;
应该避免使用eval------不安全,非常耗性能(2次,一次解析成js语句,一次执行)。
由JSON字符串转换为JSON对象的时候可以用eval,var obj =eval(‘(‘+ str +’)’)。

DOM怎样添加、移除、移动、复制、创建和查找节点

  • 创建新节点
  • 创建一个DOM片段 createDocumentFragment()
  • 创建一个具体的元素 createElement()
  • 创建一个文本节点createTextNode()
  • 添加、移除、替换、插入 appendChild() removeChild() replaceChild() insertBefore()
  • 在已有的子节点前插入一个新的子节点:???
    查找
  • 通过标签名称 : getElementsByTagName()
  • 通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的) :getElementsByName()
  • 通过元素Id,唯一性:getElementById()
  • null和undefined的区别?
  • null是一个表示”无”的对象,转为数值时为0;
  • undefined是一个表示”无”的原始值,转为数值时为NaN。
    undefined:
    (1)变量被声明了,但没有赋值时,就等于undefined。
    (2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
    (3)对象没有赋值的属性,该属性的值为undefined。
    (4)函数没有返回值时,默认返回undefined。
    null:
    (1) 作为函数的参数,表示该函数的参数不是对象。
    (2) 作为对象原型链的终点。

##new操作符具体干了什么呢?
(1)创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
(2)属性和方法被加入到 this 引用的对象中。
(3)新创建的对象由 this 所引用,并且最后隐式的返回 this 。

call() 和 apply() 的区别和作用?

apply()函数有两个参数:第一个参数是上下文,第二个参数是参数组成的数组。
如果上下文是null,则使用全局对象代替。 如:function.apply(this,[1,2,3]);
call()的第一个参数是上下文,后续是实例传入的参数序列。 如:function.call(this,1,2,3);

其他

HTTP状态码知道哪些?

  • 100 Continue 一般在发送post请求时已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息
  • 200 OK 正常返回信息 201 Created 请求成功并且服务器创建了新的资源
  • 202 Accepted 服务器已接受请求,但尚未处理
  • 301 Moved Permanently 请求的网页已永久移动到新位置。
  • 302 Found 临时性重定向 303 See Other 临时性重定向,且总是使用 GET 请求新的 URI。
  • 304 Not Modified 自从上次请求后,请求的网页未修改过。
  • 400 Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。
  • 401 Unauthorized 请求未授权。
  • 403 Forbidden 禁止访问
  • 404 Not Found 找不到如何与 URI 相匹配的资源。
  • 500 Internal Server Error 最常见的服务器端错误
  • 503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)

性能优化

  • 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;
  • 网页Gzip,CDN托管,data缓存 ,图片服务器。
  • 前端模板 :JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,
  • 每次操作本地变量,不用请求,减少请求次数
  • 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
  • 当需要设置的样式很多时设置className而不是直接操作style。
  • 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。
  • 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。
  • 图片预加载,将样式表放在顶部,将脚本放在底部 加上时间戳。

优雅降级和渐进增强

  • 优雅降级
    Web站点在所有新式浏览器中都能正常工作,如果用户使用的是老式浏览器,
    则代码会检查以确认它们是否能正常工作。由于IE独特的盒模型布局问题,
    针对不同版本的IE的hack实践过优雅降级了,为那些无法支持功能的浏览器增加候选方案,
    使之在旧式浏览器上以某种形式降级体验却不至于完全失效。

  • 渐进增强
    从被所有浏览器支持的基本功能开始,逐步地添加那些只有新式浏览器才支持的功能,
    向页面增加无害于基础浏览器的额外样式和功能的。当浏览器支持时,它们会自动地呈现出来并发挥作用。

内存泄漏

内存泄漏:任何对象在您不再拥有或需要它之后仍然存在。
垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。
如果一个对象的引用计数为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,
那么该对象的内存即可回收。
setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏。
闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)。

线程与进程的区别

一个程序至少有一个进程,一个进程至少有一个线程。 线程的划分尺度小于进程,使得多线程程序的并发性
高。 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效
率。 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序
的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 从逻辑角
度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看
做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

1.安装Node.js

Node.js是一个基于Chrome V8引擎的JavaScript运行环境。Node.js使用了一个事件驱动、非阻塞式I/O的模型,使其轻量又高效。Node.js的包管理器npm,是全球最大的开源库生态系统。
访问Node.js的官方网站:https://nodejs.org/en/

这部分自行安装

验证是否安装成功

1) 运行命令行,输入”node -v”命令。如果出现以下提示,说明”node”命令可以正常使用。
2) 运行命令行,输入”npm -v ”命令。如果出现以下提示,说明”npm”命令可以正常使用。

2.安装git

Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。

1)访问Git的官方网站:http://git-scm.com/downloads (下载安装包安装教程自行度娘)

node

2)npm包管理器安装

运行命令 npm i -g git 全局安装git

安装完成后,git version 验证git版本信息即可,如下:

3.安装Hexo

打开命令行,在命令行中输入以下命令:

运行命令 npm i -g hexo-cli 全局安装hexo,安装完成后运行 hexo -v 如下

4.本地搭建hexo博客

1)打开命令行,输入以下命令,用于创建Hexo博客目录。

$ hexo init hexoProject

2)在命令行中,进入到刚创建的目录中。

$ cd hexoProject

3)在命令行中,执行以下命令,开始初始化Hexo博客程序。

$ npm i

4)初始化完毕后,可以在命令行中输入以下命令,启动本地Hexo博客程序。

$ hexo server

5)打开浏览器,访问 http://localhost:4000 就可以访问本地的Hexo博客程序了。

5.发布博客到GitHub

1)访问GitHub的官方网站:https://github.com ,并且已经有GitHub账号,登录进去

2)登录后,点击页面右上角的”+”号。在弹出的菜单中,选择【New repository】选项。

Create a new repository 页面的话工程名必须是 你的用户名.github.io ,也就是如下图所示,前面箭头指的,初始化README勾选上,然后点击创建即可完成

然后点击 Setting 往下拉,看到 GitHub Pages ,选择master branch,save之后上方就会出现你本项目的GitHub Pages的地址了

配置Hexo程序

1)进入Hexo的安装目录,打开_config.yml配置文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 # Site
title: 网站名称
subtitle: 网站简介
description:
author: 作者
language:
timezone:

# URL
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
url: 网站域名
root: /
permalink: :category/:title.html
permalink_defaults:

...

# Deployment
## Docs: http://hexo.io/docs/deployment.html
deploy:
type: git
repo: GitHub新建工程的地址(例如https://github.com/XXX/XXX.github.io.git)
branch: master

特别注意 deploy 配置,后续发布到GitHub全靠此配置

2)在项目中安装Hexo的Git插件(如果不安装这个插件,会导致Hexo博客内容无法发布)。

运行命令 npm i hexo-deployer-git --save

发布Hexo到GitHub

1)在Hexo的安装目录中,鼠标右键选择”Git Bash Here”选项。

2)在Git命令行中,输入以下命令。

1
2
3
4
5
//生成本地的目录结构
hexo generate

// 将hexo本地目录上传至GitCafe
hexo deploy

hexo deploy 之后就可以直接访问之前的GitHub pages的地址了

更多详细内容,可以访问Hexo的官网查看