mamba


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 日程表

理解this

发表于 2019-03-23

MVC简述

发表于 2019-03-23

自己对MVC的一点理解

MVC 是什么

MVC 是一种设计模式(或者软件架构),把系统分为三层:Model数据、View视图和Controller控制器。

  • Model 数据管理,包括数据逻辑、数据请求、数据存储等功能。前端 Model 主要负责 AJAX 请求或者 LocalStorage 存储
  • View 负责用户界面,前端 View 主要负责 HTML 渲染。
  • Controller 负责处理 View 的事件,并更新 Model;也负责监听 Model 的变化,并更新 View,Controller 控制其他的所有流程。
    代码说明
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    var model = {
    data: null,
    init(){}
    fetch(){}
    save(){}
    update(){}
    delete(){}
    }
    view = {
    init() {}
    template: '<h1>hi</h1'>
    }
    controller = {
    view: null,
    model: null,
    init(view, model){
    this.view = view
    this.model = model
    this.bindEvents()
    }
    render(){
    this.view.querySelector('name').innerText = this.model.data.name
    },
    bindEvents(){}
    }

Model 和服务器交互,Model 将得到的数据交给 Controller,
Controller 把数据填入 View,并监听 View 用户操作 View,
如点击按钮,Controller 就会接受到点击事件,
Controller 这时会去调用 Model,
Model 会与服务器交互,得到数据后返回给 Controller,
Controller 得到数据就去更新 View

HTTP缓存相关内容

发表于 2019-03-21

1.Cache-Control(推荐)

设置时间长度

Cache-Control max-age=时间长度

  • Cache-Control max-age=30
    30秒内请求相同的URL 会阻拦 直接用上一次的缓存内容
  • Disable cache 开启则禁用缓存
  • 首页不设置缓存

    服务器更新数据客户端接受不到

    策略
  • 入口HTML处将URL改变—每次更新时修改URL加 查询参数,随机数或者MD5
  • Cache-Control可以让浏览器一段时间不访问服务器 直接用本地硬盘或内存作为响应
  • 浏览器会给一定内存放置缓存 如满会删除之前的
    Cache-Control的其他值
  • max-age,表示当前资源的有效时间,单位为秒。
  • no-cache表示不使用 Cache-Control的缓存控制方式做前置验证,而是使用 Etag 或者Last-Modified字段来控制缓存
  • no-store ,真正的不缓存任何东西。浏览器会直接向服务器请求原始文件,并且请求中不附带 Etag 参数(服务器认为是新请求)。

2.Expires(慎用)

设置时间点

1
response.setHeader('Expires', 'Wed, 28 Nov 2018 05:31:09 GMT')

几分几秒过期指本地时间,但如果本地时间点错误—所有缓存会全部清空

3.Cache-Control和ETag的区别

  • Cache-Control: 在设置的时间长度内会使用缓存,不需要发HTTP请求询问服务器
  • ETag: 需要发HTTP请求其中带有If-None-Match请求头,里面存的是上一次响应头的Etag内容(文件的MD5值)服务器收到请求后会提取if-none-match值,去和该资源的MD5进行对比,如果相同则返回缓存内容(返回状态码304 有请求,有响应,但是响应没有第四部分),否则返回请求资源内容
    优先使用Cache-Control 直接不请求

HTTP请求相关内容(二)

发表于 2019-03-20

常见的HTTP 状态码,并描述各状态码的意义

一篇介绍状态码的博客
HTTP状态码 维基百科

1xx消息(这一类型状态码,代表请求已被接受,需要继续处理)
2xx成功(这一类型状态码,代表请求已被成功接收,理解,并接受)
3xx重定向(这一类型状态码,代表需要客户端采取进一步的操作才能完成请求)
4xx客户端错误(这一类型状态码,代表客户端看起来发生了错误,妨碍了服务器的处理)
5xx服务器错误(这一类型状态码。代表服务器无法完成明显有效的请求)

  • 状态码200表示:请求成功。
  • 状态码202表示:服务器已接受请求,但尚未处理。
  • 状态码204表示:服务器已经成功处理了部分GET请求。
  • 状态码301表示:请求的资源已被永久的分配了新的URL。
  • 状态码302表示:请求的资源临时的分配了新的URL。
  • 状态码400表示:请求错误,请求报文中存在语法错误。
  • 状态码401表示:发送的请求需要有通过HTTP认证的认证信息。
  • 状态码403表示:禁止请求,请求被服务器拒绝了。
  • 状态码404表示:服务器上无法找到请求的资源。
  • 状态码500表示:服务器错误,服务器端在执行请求时发生了错误。
  • 状态码503表示:服务器暂时处于超负荷或正在进行停机维护,现在无法处理请求。

一个 HTTP post 请求的内容,包括四部分。

其中
第四部分的内容是 username=ff&password=123
第二部分必须含有 Content-Type 字段
请求的路径为 /path

1
2
3
4
5
6
7
8
1 POST /path HTTP/1.1
2 Host: www.baidu.com
2 User-Agent: curl/7.63.0
2 Axxept: */*
2 Content-Length: 24
2 Content-Type: application/x-www-form-urlencoded
3
4 username=ff&password=123

参考博客

一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么

1.URL输入

URL的格式定位了需要请求的地址,格式如下

协议类型:[//服务器地址[:端口号]][/资源层级UNIX文件路径]文件名[?查询][#片段ID]

2.DNS解析

DNS解析就是根据域名查找IP地址并找到服务器。DNS解析过程就是寻找哪台服务器上有你需要资源的过程,例如www.zhihu.com,其实不是知乎网站真正意义上的地址。互联网上每一台计算机的唯一标识是它的IP地址,但是IP地址并不方便记忆。用户更喜欢用方便记忆的网址去寻找互联网上的其它计算机,也就是上面提到的百度的网址。所以互联网设计者需要在用户的方便性与可用性方面做一个权衡,这个权衡就是一个网址到IP地址的转换,这个过程就是DNS解析。它实际上充当了一个翻译的角色,实现了网址到IP地址的转换。

3.TCP连接

知道了服务器的IP地址,下面就开始与服务器建立连接了。

  • 客户端向服务器发送了一个建议连接的请求(您好,我想认识你);
  • 服务器接到请求后发送同意连接的信号(好的,很高兴认识您);
  • 客户端接到同意连接的信号后,再次向服务器发送了确认信号(我也很高兴认识您),然后,客户端与服务器两者建立了联系;

    4.发送HTTP请求

    发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议中发送到服务器指定端口(HTTP协议80/8080, HTTPS协议443)。

数据经过应用层、传输层、网络层、数据链路层、物理层逐层封装,传输到下一个目的地。其中每一层的作用如下:

(5)应用层:
为应用进程提供服务,加应用层首部封装为协议数据单元。

(4)传输层:
实现端到端通信,加TCP首部封装为数据包,TCP控制了数据包的发送序列的产生,不断的调整发送序列,实现流控和数据完整。

(3)网络层:
转发分组并选择路由;加IP首部封装为IP分组。

(2)数据链路层:
相邻的节点间的数据传输;加首部[mac地址]和尾部封装为帧。

(1)物理层:
具体物理媒介中的数据传送,数据转换为比特流。
下一个目的地接受到数据后,从物理层得到数据然后经过逐层的解包 到 链路层 到 网络层,然后开始上述的处理,在经网络层 链路层 物理层将数据封装好继续传往下一个地址。
到达最终目的地,再经过5层结构,逐层剥离,最终将数据送到目的主机的目的端口。

  • 一个正常的 http request header 一般包括请求的方法,例如GET或者POST等,不常用的还有PUT 和 PATCH, DELETE, HEAD, OPTIONS,以及TRACE
  • 一般的浏览器只能发送GET和POST请求

客户端向服务器发起http请求的时候,会有一些请求信息,请求信息包括四个部分(最少三部分,第四部分可省略)

1
2
3
4
1.请求方法 URI协议/版本
2.请求头(Request Header)
3.请求正文:
4.要上传的内容

5.服务器处理请求并返回HTTP报文

HTTP响应报文也是由三部分组成:状态码,响应报头,响应报文。

6.浏览器解析并渲染页面

浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件渲染树,等到渲染树完成后,浏览器开始布局渲染树并将其绘制到屏幕上。

7.连接结束

  • 1.客户端向服务器发送一个断开连接的请求(不早了,我该走了);
  • 2.服务器接受到请求后发送确认收到请求的信号(知道了);
  • 3.服务器向客户端发送断开通知(我也该走了);
  • 4.客户端接到断开通知后断开连接并反馈一个确认信号(好的),服务器收到确认信号后断开连接;

简述Cookie、Session、(LocalStorage和SessionStorage)

发表于 2019-03-19

1.Cookie

  • 服务器通过 Set-Cookie 头给客户端一串字符串
  • 客户端每次访问相同域名的网页时,必须带上这段字符串
  • 客户端要在一段时间内保存这个Cookie
  • Cookie 默认在用户关闭页面后就失效,后台代码可以任意设置 Cookie 的过期时间
  • 大小大概在 4kb 以内
    Cookie 存在的问题
    用户可以随意篡改 Cookie

    2.Session(不翻译)

  • 将 SessionID(随机数)通过 Cookie 发给客户端
  • 客户端访问服务器时,服务器读取 SessionID
  • 服务器有一块内存(哈希表)保存了所有 session
  • 通过 SessionID 我们可以得到对应用户的隐私信息,如 id、email
  • 这块内存(哈希表)就是服务器上的所有 session
    Session 可以用 LocalStorage + 查询参数实现

    3.LocalStorage

  • LocalStorage 跟 HTTP 无关
  • HTTP 不会带上 LocalStorage 的值
  • 只有相同域名的页面才能互相读取 LocalStorage(没有同源那么严格)
  • 每个域名 localStorage 最大存储量为 5Mb 左右(每个浏览器不一样)
  • 常用场景:记录有没有提示过用户(没有用的信息,不能记录密码)
  • LocalStorage 永久有效,除非用户清理缓存

    4.SessionStorage(会话存储)

  • SessionStorage 跟 HTTP 无关
  • HTTP 不会带上 SessionStorage 的值
  • 只有相同域名的页面才能互相读取 SessionStorage(没有同源那么严格)
  • 每个域名SessionStorage 最大存储量为 5Mb 左右(每个浏览器不一样)
  • SessionStorage 在用户关闭页面(会话结束)后就失效。

5.Session 与 Cookie 的关系

一般来说,Session 基于 Cookie 来实现。

6.Cookie 和 Session 的区别

  • Cookie 保存在客户端,每次都随请求发送给 Server
  • Session 保存在 Server 的内存里,其 Session ID 是通过 Cookie 发送给客户端的

7.Cookie 和 LocalStorage 的区别

  • LocalStorage 不会随 HTTP 发给 Server
  • LocalStorage 的大小限制比 Cookie 大多了

8.LocalStorage 和 SessionStorage 的区别

  • 一个不会自动过期, LocalStorage 永久有效,除非用户清理缓存
  • 一个会自动过期。SessionStorage 在用户关闭页面(会话结束)后就失效。
总结:
  • cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。
  • cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递。
  • sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
存储大小:
  • cookie数据大小不能超过4k。
  • sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
有期时间:
  • localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
  • sessionStorage 数据在当前浏览器窗口关闭后自动删除。
  • cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭

注册和登陆(关于Cookie)

发表于 2019-03-18
我将描述一下登陆和注册之间发生了什么,将场景分为客户端和服务端,服务器是Node.JS,客户端是由JS写的

注册

1、注册请求

这是由客户端发送一个POST请求给服务端,其中包含了用户名和密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let $form = $('#signUpForm')
$form.on('submit', (e)=>{
e.preventDefault()
let hash = {}
let need = ['email', 'password', 'password_confirmation']
need.forEach((name)=>{
let value = $form.find(`[name=${name}]`).val()
hash[name] = value
})
$form.find('.error').each((index, span)=>{
$(span).text('')
})
$.post('/sign_up', hash)
.then((response)=>{
console.log(response)
}, (request)=>{
let {errors} = request.responseJSON
if(errors.email && errors.email === 'invalid'){
$form.find('[name="email"]').siblings('.error')
.text('邮箱格式错误')
}
})
})

2、服务器检查

服务器需要检查发送过来的用户名是否注册过,如果注册过就返回失败,如果没有注册过就写入数据库

3、返回

写入数据库成功,就将注册成功返回给用户

登录

1、输入账号密码

输入账号密码,并POST发送给服务器,可以检查输入格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let $form = $('#signInForm')
$form.on('submit', (e) => {
e.preventDefault()
let hash = {}
let need = ['email', 'password']
need.forEach((name) => {
let value = $form.find(`[name=${name}]`).val()
hash[name] = value
})
$form.find('.error').each((index, span) => {
$(span).text('')
})
$.post('/sign_in', hash)
.then((response) => {
window.location.href = '/'
}, (request) => {
alert('邮箱与密码不匹配')
})
})

2、服务器检查

获取账号密码,服务器查询数据库,看是否有对应的账号存在

3、返回

如果有对应的存在就返回登录成功,如果没有,就返回登录失败

Cookie

在上面的注册和登录过程中会有一些问题,网站是如何判断登录与否的,有些页面只有登录才可以访问,另外,如何来确认登录的是谁,这样才不会搞混乱,这时就需要引入Cookie来解决这些问题

设置Cookie

在登录的一瞬间,服务器通过Set-Cookie,例如

1
response.setHeader('Set-Cookie', `sign_in_email=${email}`)

告诉浏览器,在这个用户上做了个标记,以后只要相同的源的请求都会带上这个Cookie,服务器Set-Cookie的是什么,浏览器Cookie就会是什么。

期限

Cookie并不是永久有效的,就像游乐场的门票一样,你在游乐场去任何地方都需要这张门票,但是这个门票会有期限,这个期限可以自己设置,和关闭浏览器便失效的会话期Cookie不同,持久性Cookie可以指定一个特定的过期时间(Expires)或有效期(Max-Age)。

1
response.setHeader('Set-Cookie', `id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT`)

当Cookie的过期时间被设定时,设定的日期和时间只与客户端相关,而不是服务端。

特点

  • 服务器通过Set-Cookie响应头来设置Cookie
  • 浏览器得到Cookie后,每次请求都会带上Cookie
  • 服务器读取Cookie就知道登录用户的信息
  • Cookie存在电脑上的一个秘密的文件位置
  • Cookie并不安全,可以做假
  • Cookie有效期的默认时间由浏览器决定,后端可以强制设置
  • 不同浏览器上的Cookie不可以互通

vue-cli项目部署到GitHub Pages上

发表于 2019-03-15

1. Node.js安装(自带npm)

2. Vue-cli 安装

  • 全局安装vue-cli

    1
    npm install -g vue-cli
  • 进入目录-初始化项目

    1
    vue init webpack  my-project
  • 进入项目

    1
    cd my-project
  • 安装依赖

    1
    npm install
  • 启动项目

    1
    npm run dev

3. 修改Vue项目配置

  • 大家都知道使用npm run build进行打包,这个时候你直接打开dist ‘/‘ 下的index.html,会发现文件可以打开,但是所有的js,css,img等路径有问题是指向根目录的,此时需要修改config/index.js里的assetsPublicPath的 ‘/‘, 初始项目是 ‘/‘ 他是指向项目根目录的也是为什么会出现错误,这时改为 ‘. /‘
  • 将 webpack.prod.conf.js 中的 removeAttributeQuotes 改为 false

  • 注释/dist/

4. 项目打包

1
npm run build

- 项目测试

1
http-serevr ./dist

5. 在GitHub上创建与本地项目同名的远程仓库

6. 将本地项目push到已经创建好的远程仓库

点击Settings进入后点击Source里的master branch得到的链接就是项目预览链接

vue实例,生命周期钩子,文本插值,数据绑定,指令事件,语法糖

发表于 2019-03-08

1.1 vue实例和数据绑定

  1. 1
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>

通过构造函数 Vue 就可以创建一个 Vue 的根实例,并启动 Vue 应用—入口

var app =new Vue({ 
    el:'', 
    data:{ } 
    })

2.必不可少的一个选项就是 el 。 el 用于指定一个页面中己存在的 DOM 元素来挂载 Vue实例,可以是标签。也可以是css语法
3.通过 Vue 实例的 data 选项 选项,可以声明应用内需要双向绑定的数据。建议所有会用到的数据都预先在 data 内 声明,这样不至于 将数据散落在业务逻辑中,难以维护。也可以指向一个已经有的变量
4.挂载成功后,我们可以通过 app.$el 来访问该元素。Vue 提供了很多常用的实例属性与方法,比如 el,Vue实例本身也代理了data对象里的所有属性,所以可以这样访问

  • 访问vue实例的属性:都以$开头,如app.$data app.$el
  • 访问data元素的属性– 直接app.属性名,app.msg

1.2 生命周期钩子

jquery—$(document).ready()

  • created 实例创建完成后调用,此阶段完成了数据的观测等,但尚未挂载, $el 还不可用。需要初始化处理一些数据时会比较有用,.—-还未挂载
  • mounted el 挂载到实例上后调用,一般我们的第一个业务逻辑会在这里开始 。相当于 $(document).ready()—刚刚挂载
  • beforeDestroy 实例销毁之前调用。主要解绑一些使用 addEventListener 监听的事件等。

1.3 文本插值和表达式

语法:使用双大括号( Mustache 语法)“{{}}”是最基本的文本插值方法,它会自动将我们双向绑定的数据实时显示出来,

用法

在{{}}中,除了简单的绑定属性值外,还可 以使用 JavaScript 表达式进行简单的运算 、 三元运算等 —实例 Vue .js 只支持单个表达式,不支持语句和流控制。

{ { 6+6 *3} }---可以进行简单的运算

{ { 6<3 ? msg :a} }---可以用三元运算符

{ {if(6>3){} }-----注意:文本插值的形式,其中不能书写表达式,支持单个表达式

{ {var a = 6} }--也是多行表达式----var a ;a = 6; 〈!一这是语旬,不是表达式 一〉

{{ var book = "Vue . js 实战 "} 〈!一不能使用流控制,要使用三元运算 一〉

{ { if (ok) return msg } }

过滤器

Vue. 支持在{{}}插值的尾部添加一小管道符 “ | ” 对数据进行过滤,经常用于格 式化文本,比如字母全部大写、货币千位使用逗号分隔等。过滤的规则是自定义 的, 通过给 Vue 实例添加选项 filters 来设置 过滤器: {{ data | filter1 |filter2}} {{date | formatDate(66,99)}}
中的第一个和第二个参数,分别对应过滤器的第二个和 第三个参数

指令和事件

指令( Directives )是 Vue 模板中最常用的一项功能,它带有前缀 v-,能帮我们 快速完成DOM操作。循环渲染。显示和隐藏
本节目标 v-text , v-html , v-bind , v-on
v­-text:­解析文本 和{{}} 作用一样
v­-html:解析html
v­-bind:v-­bind 的基本用途是动态更新 HTML 元素上的属性,比如 id 、 class 等,本节只介绍基本章节,后面章节会更加深入详细讲述
v­-on:它用来绑定事件监听器
v-­on具体介绍
在普通元素上, v­-on 可以监听原生的 DOM 事件,除了 click 外,还有 dblclick、 keyup, mousemove 等。表达式可以是一个方法名,这些方法都 写在 Vue 实例的 methods 属性内,并且是函数的形式,函数内的 this 指向 的是当前 Vue 实例本身,因此可以直接使用 this.xxx 的形式来访问或修改数 据
vue中用 到的所有方法都定义在methods中

语法糖

语法糖是指在不影响功能的情况下 , 添加某种简洁方法实现同样的效果 , 从而更加方便程 序开发。 v-bind : (冒号) v-on @

JSON,JSONP,AJAX简述

发表于 2019-02-21

前言:一个网站如果要完整的运行出来,必须要前端与后端结合。本文就简略的介绍一下这几个技术:JSONP、JSON、AJAX。

1、如何发请求

  • 用 form 可以发请求,但是会刷新页面或新开页面
  • 用 a 可以发 get 请求,但是也会刷新页面或新开页面
  • 用 img 可以发 get 请求,但是只能以图片的形式展示
  • 用 link 可以发 get 请求(必须放在head中),但是只能以 CSS、favicon 的形式展示
  • 用 script 可以发 get 请求(需要放在head或body中),但是只能以脚本的形式运行

以上方法除了form 都无法实现get、post、put、delete 等请求都行,想以什么形式展示就以什么形式展示。

2、什么是 JSONP?

请求方:a网站 的前端程序员(浏览器)
响应方:b网站 的后端程序员(服务器)

  • 请求方动态创建 script,src 指向响应方,同时传一个查询参数 ?callbackName=yyy
  • 响应方根据查询参数callbackName,构造形如

    yyy.call(undefined, ‘你要的数据’)
    yyy(‘你要的数据’)
    这样的响应

  • 浏览器接收到响应,就会执行 yyy.call(undefined, ‘你要的数据’)

  • 那么请求方就知道了他要的数据
    这就是 JSONP
注:两个约定:

callbackName 一般都叫 callback
yyy函数 一般使用 随机数来命名 如:mamba12312312312321325()

3、JSONP 为什么不支持 POST

因为JSONP是动态创建script来实现的,而动态创建script不支持post请求,只能用get请求。

4、jQuery 的 JSONP方法

1
2
3
4
5
6
7
8
9
$.ajax({
url: "http://jack.com:8002/pay",
dataType: "jsonp",
success: function( response ) {
if(response === 'success'){
amount.innerText = amount.innerText - 1
}
}
})
需要注意的是:虽然jQuery中,把JSONP归到ajax方法中,但实际上JSONP和ajax没有一丝关系,是核心思路完全不同的两种方法。

5、什么是AJAX

Jesse James Garrett 将如下技术取名叫做 AJAX:异步的 JavaScript 和 XML,即 Async JavaScript And XML
  • 使用 XMLHttpRequest 发请求
  • 服务器返回 XML 格式的字符串
  • JS 解析 XML,并更新局部页面

注:现在已经很少使用XML,更多的使用JSON,即服务器返回符合JSON语法的字符串。

6、如何使用 XMLHttpRequest

  • readyState属性:请求的5种状态,值为0~4,至少一定要知道值为4的含义。
0 :UNSENT (未打开) open()方法还未被调用.
1 :OPENED (未发送) open()方法已经被调用.
2 :HEADERS_RECEIVED (已获取响应头) send()方法已经被调用, 响应头和响应状态已经返回.
3 :LOADING (正在下载响应体) 响应体下载中; responseText中已经获取了部分数据.
4 :DONE (请求完成) 整个请求过程已经完毕.
核心代码如下:

前端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
xxx.addEventListener('click',(e) => {
let request = new XMLHttpRequest() //产生request对象
request.open('post','/xxx') // 配置request对象
request.send() // 发送这个对象
request.onreadystatechange = ()=>{ // 监听request对象的readyState的变化
if(request.readyState === 4){
console.log('请求完成')
if(request.status >= 200 && request.status < 400){
console.log('请求成功')
let string = request.responseText
console.log(string)
let obj = JSON.parse(string)
console.log(obj.note.body)

}else{
console.log('请求失败')
}
}
}
})

后端代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(path ==='/xxx'){
response.setHeader('Content-Type','text/json;charset=utf-8')
response.write(`
{
"note":{
"to":"Enoch",
"from":"Snow",
"heading":"Say Hi",
"body":"Hello Wrold"
}
}
`)
response.end()
}
JSON(JavaScript Object Notation)是一种由道格拉斯·克罗克福特构想和设计、轻量级的数据交换语言。

7、JSON —— 一门新语言

  • JSON的全部语法
  • JSON的数据类型:
  • JSON 与 JS 的区别:
JSON 和 JS 是两门不同的语言,JSON借鉴(或者说抄袭)了JavaScript的部分语法。
JSON没有undefined和function
JSON 字符串的首尾必须使用双引号”

举例:

1
2
3
4
5
6
"note":{
"to":"mamba",
"from":"Snow",
"heading":"Say Hi",
"body":"Hello Wrold"
}

8、同源策略

阮一峰博客-浏览器同源政策及其规避方法
简单的说就是:只有 协议+端口+域名这三项 一模一样才允许发 AJAX 请求。
举个例子:

1.http://zhihu.com 可以向 http://www.zhihu.com 发 AJAX 请求吗 no
2.http://zhihu.com:80 可以向 http://zhihu.com:81 发 AJAX 请求吗 no

9、CORS 跨域

阮一峰博客-跨域资源共享 CORS 详解

CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。
  • 浏览器必须保证只有 协议+端口+域名 一模一样才允许发 AJAX 请求
  • CORS 策略 可以告诉浏览器,我俩一家的,别阻止他
  • 突破同源策略 === 跨域
    举个例子:
    这样写就可以让(http://mamba.com:8001) 这个网站向我的网站发请求
    response.setHeader(‘Access-Control-Allow-Origin’,’http://mamba.com:8001')
    参考

初级前端需要知道的基础知识

发表于 2019-02-19

本文罗列十道基础题目,总结一下近期的知识。

1.第1题: 请写出一个符合 W3C 规范的 HTML 文件,要求

页面标题为「我的页面」
页面中引入了一个外部 CSS 文件,文件路径为 /style.css
页面中引入了另一个外部 CSS 文件,路径为 /print.css,该文件仅在打印时生效
页面中引入了另一个外部 CSS 文件,路径为 /mobile.css,该文件仅在设备宽度小于 500 像素时生效
页面中引入了一个外部 JS 文件,路径为 /main.js
页面中引入了一个外部 JS 文件,路径为 /gbk.js,文件编码为 GBK
页面中有一个 SVG 标签,SVG 里面有一个直径为 100 像素的圆圈,颜色随意
注意题目中的路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>我的页面</title>
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="/print.css" media="print">
<link rel="stylesheet" href="/mobile.css" media="(max-width: 500px)">
</head>

<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="100" r="50" fill="red" />
</svg>
</body>
<script src="/main.js"></script>
<script src="/gbk.js" charset="GBK"></script>
</html>

第2题: 移动端是怎么做适配的?

回答要点:
1.meta viewport
2.媒体查询
3.动态 rem 方案
1.在html中的head加入下面这个代码

1
2
3
4
5
6
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,user-scalable=no">
//width=device-width: 让当前viewport宽度等于设备宽度
//user-scalable=no: 禁止用户缩放
//initial-scale=1.0: 设置页面的初始缩放值为不缩放
//maximum-scale: 允许用户的最大缩放值为1.0
//minimun-scale: 允许用户的最小缩放值为1.0

2.不同的设备采取不同的样式,实现该方法应用媒体查询

使用 media 查询来响应不同分辨率
如在引入外部样式时,只有满足条件最大宽度为425px时,example.css才生效:

1
<link rel="stylesheet" media="(max-width: 425px)" href="example.css" />

在CSS内部,也可以用media来设置特定的情况下让某些样式生效,如下,即当最大宽度为425px时,该样式生效:

1
2
3
4
5
<style>
@media (max-width: 425px) {
……
}
</style>

  • 使用动态 REM 方案保证手机端的显示效果
  • rem指的是根元素的字体大小,根元素一般指的是html
    3.动态rem即在js中设置
    1
    2
    var pageWidth = window.innerWidth
    document.write('<style>html{font-size:'+pageWidth/10+'px;}</style>')

这样可以保证整体页面的比例,不会导致页面变形

(2) 使用scss直接将px转换成rem,减少自己计算时间

例子:

1
2
3
4
5
6
@function px2rem($px){
@return $px/$designWidth*5 + rem;
}

$designWidth: 750;
1rem = px2rem(150) =150px;

第3题: CSS3 实现圆角矩形和阴影怎么做?

CSS3 MDN文档
css3 中的新特性,比较常用的:
新增加的伪类如nth-child()等、flex布局、使用transform对元素进行变换、transition过渡,通过定义keyframes做一些动画效果、添加阴影box-shadow、移动端适配中会用到媒体查询等

  • 阴影包括box-shadow和text-shadow:
    1
    2
    box-shadow: inset 1px 2px 3px blue
    text-shadow: inset 1px 2px 3px blue

以上代码一个在边框内,inset(阴影向内) ,offset-x(x轴上的偏移量) 1px, offset-y(y轴上的偏移量) 2px, blur-radius(模糊半径大小) 3px的蓝色box阴影和text阴影
box-shadow 文档
box-shadow 可以使用一个或多个投影,如果使用多个投影时必须需要用逗号“,”分开。用法如下:

  • 对象选择器 {box-shadow:inset x-offset y-offset blur-radius spread-radius color}
  • 对象选择器 {box-shadow:投影方式 X轴偏移量 Y轴偏移量 阴影模糊半径 阴影扩展半径 阴影颜色}

用borde-radius实现圆形矩角

1
border-radius: 2px;

以上代码设置了一个四个圆角角度为2px的圆角矩形
border-radious 文档

  • 后面接一个值时:为元素的四个角都设置相同的圆角;
  • 后面接两个值:第一个值设置的是左上角和右下角的值,第二个值指的是右上角和左下角的值;
  • 后面接四个值时:四个值分别设置的圆角顺序为,从左上角开始顺时针的四个角,即分别为左上角,右上角,右下角,左下角。
  • 如果我们要做一个圆形,可以这么写:border-radious:50%;

使用圆角还可以做椭圆:border-radius还可以用斜杠设置第二组值。这时,第一组值表示水平半径,第二组值表示垂直半径。第二组值也可以同时设置1到4个值,应用规则与第一组值相同。如:border-radius: 1px 2px 3px 4px / 5px 4px 3px 3px;

第4题: 什么是闭包? 闭包的用途?

  • “函数”和”函数内部能访问到的变量(也叫环境)”的总和,就是一个闭包。
  • JavaScript有两种作用域,全局作用域和函数作用域。函数内部可以直接读取全局变量。但是,在函数外部无法读取函数内部声明的变量。换言之。如果一个函数,使用了它范围外的变量,那么”这个函数+这个变量”就叫做闭包。
  1. 闭包的用途:我们之所以使用闭包,是因为闭包可以用来「间接访问一个变量」。换句话说,「隐藏一个变量」。例如函数中的局部变量,在执行完毕之后就会死掉,在其他地方是访问不到的,而闭包就是用来暴露一个访问器(函数),用于间接访问到这个变量。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function f1(){
    var n = 1;
    function f2(){
    console.log(n)
    }
    return f2
    } //这段代码中函数 f2 和变量 n 的总和就叫闭包

    var local = '变量'
    function foo(){
    console.log(local)
    } //这段代码中函数 foo 和变量 local的总和就叫闭包
  2. 让这些变量始终保持在内存中(缓存数据)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function f1(n){
    return function(){
    return n++;
    }
    }
    var a = f1(1)
    a() //1
    a() //2
    a() //3
    //这段代码中,闭包使得内部变量记住上一次调用时的运算结果。
  3. 封装对象的私有属性和私有方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function f1(n){
    return function(){
    return n++;
    }
    }
    var a = f1(1)
    a() //1
    a() //2
    a() //3

    var b = f1(5)
    b() //5
    b() //6
    b() //7
    //这段代码中,a 和 b 是相互独立的,各自返回自己的私有变量。

    }
总结:闭包的用处:
可以间接调用函数内部的局部变量。
可以让这些变量的值始终保持在内存中。
可以暂存数据,给变量开辟私密空间,避免外部污染。

第5题: call、apply、bind 的用法分别是什么?

在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向。

  • call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表)。
  • apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数。
  • bind() 方法创建一个新的函数,被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
对于apply、call二者而言,作用完全一样,只是接受参数的方式不太一样,call需要把参数按顺序传递进去,而 apply则是把参数放在数组里。
  • apply 、call、bind三者都是用来改变函数的this对象的指向的;
  • apply、 call、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
  • apply、 call 、bind三者都可以利用后续参数传参;
  • bind 是返回对应函数,便于稍后调用;apply 、call则是立即调用 。
举例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var obj = {
x: 21,
};

var foo = {
getX: function() {
return this.x;
}
}

console.log(foo.getX.bind(obj)()); //21
console.log(foo.getX.call(obj)); //21
console.log(foo.getX.apply(obj)); //21

// 三个输出的都是21,但是注意看使用 bind() 方法的,他后面多了对括号。
//也就是说,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。

参考博客

第6题:请说出至少 8 个 HTTP 状态码,并描述各状态码的意义

一篇介绍状态码的博客
HTTP状态码 维基百科

  • 1xx消息(这一类型状态码,代表请求已被接受,需要继续处理)
  • 2xx成功(这一类型状态码,代表请求已被成功接收,理解,并接受)
  • 3xx重定向(这一类型状态码,代表需要客户端采取进一步的操作才能完成请求)
  • 4xx客户端错误(这一类型状态码,代表客户端看起来发生了错误,妨碍了服务器的处理)
  • 5xx服务器错误(这一类型状态码。代表服务器无法完成明显有效的请求)

1.状态码200表示:请求成功。
2.状态码202表示:服务器已接受请求,但尚未处理。
3.状态码204表示:服务器已经成功处理了部分GET请求。
4.状态码301表示:请求的资源已被永久的分配了新的URL。
5.状态码302表示:请求的资源临时的分配了新的URL。
6.状态码400表示:请求错误,请求报文中存在语法错误。
7.状态码401表示:发送的请求需要有通过HTTP认证的认证信息。
8.状态码403表示:禁止请求,请求被服务器拒绝了。
9.状态码404表示:服务器上无法找到请求的资源。
10.状态码500表示:服务器错误,服务器端在执行请求时发生了错误。
11.状态码503表示:服务器暂时处于超负荷或正在进行停机维护,现在无法处理请求。

第7题:请写出一个 HTTP post 请求的内容,包括四部分。

其中
第四部分的内容是 username=ff&password=123
第二部分必须含有 Content-Type 字段
请求的路径为 /path

1
2
3
4
5
6
7
8
1 POST /path HTTP/1.1
2 Host: www.baidu.com
2 User-Agent: curl/7.63.0
2 Axxept: */*
2 Content-Length: 24
2 Content-Type: application/x-www-form-urlencoded
3
4 username=ff&password=123

参考博客

第8题: 请说出至少三种排序的思路,这三种排序的时间复杂度分别为

  • O(n*n)
  • O(n log2 n)
  • O(n + max)
冒泡排序O(n*n)

每次比较两个相邻的数字作比较,小的放前面,大的放后面,这样一轮下来小的数字就放在了最前面,直到所有的数字排完。

快速排序O(nlogn)

到其中一个数作为标杆,小于标杆的数字放在左边,大于标杆的数字放在右边,这一次排完之后再重复前面的操作,直到有一个数字为止。

基数排序O(n+max)

所有正整数总从最低的位为开始,把相同的排列在一起,然后再排十位,不够的补零。然后再依次排下一位,这样排列下来。再挨个去取即可得到有序数列。

第9题: 一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么

1.URL输入

URL的格式定位了需要请求的地址,格式如下

  • 协议类型:[//服务器地址[:端口号]][/资源层级UNIX文件路径]文件名[?查询][#片段ID]
2.DNS解析
  • DNS解析就是根据域名查找IP地址并找到服务器。DNS解析过程就是寻找哪台服务器上有你需要资源的过程,例如www.zhihu.com,其实不是知乎网站真正意义上的地址。互联网上每一台计算机的唯一标识是它的IP地址,但是IP地址并不方便记忆。用户更喜欢用方便记忆的网址去寻找互联网上的其它计算机,也就是上面提到的百度的网址。所以互联网设计者需要在用户的方便性与可用性方面做一个权衡,这个权衡就是一个网址到IP地址的转换,这个过程就是DNS解析。它实际上充当了一个翻译的角色,实现了网址到IP地址的转换。
3.TCP连接
知道了服务器的IP地址,下面就开始与服务器建立连接了。
  • 客户端向服务器发送了一个建议连接的请求(您好,我想认识你);
  • 服务器接到请求后发送同意连接的信号(好的,很高兴认识您);
  • 客户端接到同意连接的信号后,再次向服务器发送了确认信号(我也很高兴认识您),然后,客户端与服务器两者建立了联系;
4.发送HTTP请求
  • 发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议中发送到服务器指定端口(HTTP协议80/8080, HTTPS协议443)。

  • 数据经过应用层、传输层、网络层、数据链路层、物理层逐层封装,传输到下一个目的地。其中每一层的作用如下:

#####(5)应用层:
为应用进程提供服务,加应用层首部封装为协议数据单元。

#####(4)传输层:
实现端到端通信,加TCP首部封装为数据包,TCP控制了数据包的发送序列的产生,不断的调整发送序列,实现流控和数据完整。

#####(3)网络层:
转发分组并选择路由;加IP首部封装为IP分组。

#####(2)数据链路层:
相邻的节点间的数据传输;加首部[mac地址]和尾部封装为帧。

#####(1)物理层:
具体物理媒介中的数据传送,数据转换为比特流。
下一个目的地接受到数据后,从物理层得到数据然后经过逐层的解包 到 链路层 到 网络层,然后开始上述的处理,在经网络层 链路层 物理层将数据封装好继续传往下一个地址。
到达最终目的地,再经过5层结构,逐层剥离,最终将数据送到目的主机的目的端口。

  • 一个正常的 http request header 一般包括请求的方法,例如GET或者POST等,不常用的还有PUT 和 PATCH, DELETE, HEAD, OPTIONS,以及TRACE
  • 一般的浏览器只能发送GET和POST请求

    客户端向服务器发起http请求的时候,会有一些请求信息,请求信息包括四个部分(最少三部分,第四部分可省略)
    1.请求方法 URI协议/版本
    2.请求头(Request Header)
    3.请求正文:
    4.要上传的内容

5.服务器处理请求并返回HTTP报文
HTTP响应报文也是由三部分组成:状态码,响应报头,响应报文。
6.浏览器解析并渲染页面
浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件渲染树,等到渲染树完成后,浏览器开始布局渲染树并将其绘制到屏幕上。
7.连接结束
1.客户端向服务器发送一个断开连接的请求(不早了,我该走了);
2.服务器接受到请求后发送确认收到请求的信号(知道了);
3.服务器向客户端发送断开通知(我也该走了);
4.客户端接到断开通知后断开连接并反馈一个确认信号(好的),服务器收到确认信号后断开连接;

第10题:如何实现数组去重?

假设有数组 array = [1,5,2,3,4,2,3,1,3,4]
你要写一个函数 unique,使得
unique(array) 的值为 [1,5,2,3,4]
也就是把重复的值都去掉,只保留不重复的值。
要求:
不要做多重循环,只能遍历一次
请给出两种方案,一种能在 ES 5 环境中运行,一种能在 ES 6 环境中运行(提示 ES 6 环境多了一个 Set 对象

ES5写法1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function unique(array){
var tempArr = []
var hash = {}
for(var i=0; i<array.length; i++){
if(hash[array[i]] === undefined){
tempArr.push(array[i])
hash[array[i]] = 1
}
}
return tempArr
}

var array = [1,5,2,3,4,2,3,1,3,4]
unique(array)
  • 当数组中出现数字3 和字符串 ‘3’时,第一种写法会将其当成同一个值返回
ES5写法2:
1
2
3
4
5
6
7
8
9
10
11
12
function uniqueCom(array) {
var hash = {}
var tempArray = []
array.forEach(function(value) {
var key = (typeof value) + value;
if (!hash[key]) {
hash[key] = true
tempArray.push(value)
}
})
return tempArray
}
  • 第二种写法可以判断数字3 和字符串 ‘3’的不同。
    ES6写法: 使用Set对象,MDN文档:
    1
    2
    3
    function unique(array){
    return Array.from(new set(array))
    }
1…345

张哲

48 日志
GitHub E-Mail
© 2019 张哲
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4