我的博客

每天进步一点点


  • 首页

  • 标签

  • 分类

  • 归档

HTML5知识点总结

发表于 2019-05-19 | 分类于 html5
  • 语义
    • 区块和段落元素
      • section article nav header footer aside hgroup
    • 音频和视频
      • audio video
    • 表单改进
      • 提供强制校验的API
        • 内置提供:valid和:invalid这两个伪类,来设置元素通过或未通过时的样式
        • required属性 如果输入为空,表单不会提交,并会提示错误
        • pattern属性 支持正则表达式
        • minlength maxlength 来强制条目的长度
      • output元素:执行计算然后在output元素中展示结果
    • 改进iframe,新增sandbox seamless srcdoc属性
  • 流通性(通信)
    • Web sockets
      • 在单个TCP连接上进行全双工通讯的协议
      • 替代了Ajax轮询(缺点是:每次都包含体积很大的HTTP请求头,节省了服务器资源和带宽)的方案
      • [https://www.runoob.com/html/html5-websocket.html]
    • 服务器向浏览器推送事件,允许网页自动获得来自服务器的更新
      • [https://www.runoob.com/html/html5-serversentevents.html]
    • webRTC 即时通信,类似于视频会议
  • 离线 & 存储
    • 离线资源缓存
    • 在线和离线事件,用于检测是否存在可用网络连接
    • 客户端会话和持久化存储(DOM存储)
    • IndexedDB 能够在浏览器存储大量结构化数据
  • 多媒体
    • audio video
    • WebRTC 即时通信
    • 提供camera api,允许使用计算机的摄像头
  • 绘画 & 效果
    • canvas
    • WebGL 3D图像效果
    • SVG
  • 性能 & 集成
    • web workers 把JavaScript计算委托给后台线程
    • History API 允许操作浏览器的历史记录
    • contentEditable标准化
    • 拖放API
    • requestAnimationFrame 允许控制动画渲染以获得更优性能
    • 全屏API
    • 在线离线事件(处于当前tab和离开当前tab)
  • 设备访问
    • 摄像头
    • 触控事件
    • 地理位置定位
    • 检测设备方向

面试学习5

发表于 2019-03-20

css3动画

transition

  • transition: 执行变化的属性 变化持续的时间 变化的样式
  • 并不是所有的属性都支持
  • 需要事件触发,没办法自动发生
    1
    transition: all 2s ease-in-out

animation

  • 可以设置任意多的关键帧,所以动画比较丰富
    1
    2
    3
    4
    5
    @keyframes 动画名 {
    0% { top: 0; left: 0px}
    50% { top: 30px; left: 20px; }
    100% { top: 0; left: 30px;}
    }

transform

  • 顾名思义就是变形的意思,这里涉及的变形包括rotate旋转、skew扭曲、scale缩放、translate移动、matrix矩阵变形
  • 常用的有:translate(x,y)进行2d转换、scale(x,y)进行2d缩放、rotate(角度数)进行2d旋转

类数组转数组

  • Array.prototype.slice.call(类数组),因为数组slice方法如果不带任何参数,就是默认将数组从头到尾都浅拷贝一份
  • Array.from()
  • 对于有遍历器接口的类数组,可以直接使用扩展运算符

关于this

  • this指向:指向最后一个调用它的对象
  • 如何改变this指向
    • new
    • 箭头函数
    • call/apply/bind
    • _this = this

函数调用有4种方式:直接调用、作为对象的方法、构造函数、call/apply

dns解析过程

  • 浏览器缓存
  • 操作系统缓存
  • 本地Host文件
  • 路由器缓存
  • 运营商DNS服务
  • 根域名服务器
  • 顶级域名服务器
  • 主域名服务器
  • 保存结果至缓存

TCP三次握手主要目的是要数据的发送和接收同步,通俗地讲就是

  • A:要连接你
  • B:好的收到,是现在连接吗
  • A:现在连接吧

TCP四次挥手

  • A:我要走了
  • B:好的收到,要等一下,我这边还有几句话没说完
  • B:我说完了,可以走了
  • A:那拜拜了

TCP和UDP的区别

  • 有连接和无连接
  • 保证数据的正确性和可能发生丢包
  • 保证数据顺序,后者不保证

==运算符会首先将操作对象转化为相同类型,具体表现为

  • 只要其中有一个是NaN,就返回false
  • 如果两个都是null或者undefined,返回true
  • 如果两个都是基本数据类型,且类型不同,则将两者都将转化数值类型再比较
  • 如果是引用类型值,则将其转化为基本类型再比较

bfc三个特性

  • 防止外边距折叠(margin塌陷)
  • 包含浮动元素
  • 防止内容被浮动元素覆盖

如何获取url信息

  • URL很多信息都存储在window.location这个属性中,打印即可
  • 经常会用到如何获取URL的参数及参数值,具体如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function GetRequest() {
    var url = window.location.search; //获取url中"?"符后的字串
    var theRequest = new Object()
    if (url.indexOf("?") != -1) {
    var str = url.substr(1)
    strs = str.split("&")
    for(var i = 0; i < strs.length; i ++) {
    theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1])
    }
    }
    return theRequest
    }

es5和es6关于类的区别

  • 前者的toString方法是可枚举的,后者不可枚举

面试学习4

发表于 2019-03-19

浏览器跨标签通信

  • 获取句柄,父页面通过window.open()这个接口打开子页面,然后设置当子页面加载onload的时候,将传递的信息作为postMessage的参数;这时子页面上就可以调用window.onmessage接口,获取到父页面传递过来的信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //A.html
    const child = window.open('child.html', 'child')
    child.onload = () => {
    child.postMessage('message', location.origin)
    }
    //B.html
    window.onmessage = event => {
    event.data
    }
  • localstorage、cookie

内存泄漏

  • 意外的全局变量,使得这个变量挂在window对象上,没办法被清除,解决方法是:使用严格模式、将其设置为null
  • 忘记关停定时器,导致定时器内的dom节点一直被引用,没办法回收
  • 没有移除事件监听器
  • 闭包
  • 本以为已经移除了一些没用的dom节点,没想到移除的dom节点还被其他节点所引用,导致无法彻底移除

面试学习3

发表于 2019-03-16

盒模型

  • IE盒模型
    • width = border + padding + content
  • W3C标准盒模型
    • width = content

可以通过box-sizing来设置不同的盒模型,该属性默认是content-box,可以改为border-box

怪异模式和标准模式

  • 盒模型不同

尽量用border-box,这样可以直接设置子元素的width,不受padding的影响

new这个过程发生了什么

  • 创建了一个空对象
  • 将构造函数的this指向这个空对象
  • 为新对象添加属性
  • 返回新对象

vue双向绑定原理:数据劫持、发布-订阅模式

具体实现:数据劫持是通过Object.defineProperty()

视图到数据这一块可以通过事件监听来实现

比较关键的就是数据到视图这一块

定义一个observer观察者,用来劫持并监听所有数据的变化,如果有变化,就通知订阅者

定义一个watcher订阅者,接收来自观察者的信息,当数据发生变化时,执行函数,更新视图

定义一个compile,用来扫描解析节点和指令、初始化模板数据、初始化订阅者

任何没有设置doctype的Html都将以混杂模式来解析

浅拷贝

  • object.assgin
  • 展开运算符

深拷贝

  • JSON.parse(JSON.stringify(obj))
  • 递归逐一赋值

new运算符的执行过程

  • 创建一个空对象
  • 将构造函数的this指向空对象
  • 为空对象添加属性
  • 返回该对象

es6推出的新数据结构set和map

  • set集合中的元素是唯一的、不重复
  • map和对象类似,区别在于map的键可以是任意数据类型
  • 两者都提供了一些方法,让我们处理数据

函数柯里化

  • 为函数预置参数,以便重复利用

数组乱序

1
2
3
arr.sort(function (){
return Math.random() - 0.5
})

数组扁平化

1
2
3
arr.flat = function (){
return this.toString().split(',').map(item => +item)
}

数组去重

1
2
3
4
5
6
7
8
9
function only(arr){
var newarr = []
for(var i = 0; i < arr.length; i++){
if(newarr.indexOf(arr[i]) == -1){
newarr.push(arr[i])
}
}
return newarr
}

面试学习2

发表于 2019-03-12

正则去掉字符串首尾空格

  • str.replace(/(^\s)|(\s$)/g, ‘’)

输入URL发生了什么

  1. 当发送一个 URL 请求时,不管这个 URL 是 Web 页面的 URL 还是 Web 页面上每个资源的 URL,浏览器都会开启一个线程来处理这个请求,同时在远程 DNS 服务器上启动一个 DNS 查询(浏览器缓存->系统缓存->路由器缓存)。这能使浏览器获得请求对应的 IP 地址。
  2. 浏览器与远程 Web 服务器通过 TCP 三次握手协商来建立一个 TCP/IP 连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。
  3. 一旦 TCP/IP 连接建立,浏览器会通过该连接向远程服务器发送 HTTP 的 GET 请求。远程服务器找到资源并使用 HTTP 响应返回该资源,值为 200 的 HTTP 响应状态表示一个正确的响应。
  4. 此时,Web 服务器提供资源服务,客户端开始下载资源。
  5. 浏览器解析HTML生成DOM树,在根据CSS生成渲染树;浏览器缓存相应的信息,查看是否需要更新缓存;呈现页面。

缓存4个字段及优先级

  • Expires
  • Cache-control:max-age=6000(毫秒)/no-cache/no-store/private/public
  • last-modified
  • Etag

强缓存>弱缓存
cache-control>expires
ETag > Last-Modified

ctrl f5 所发送的请求头包含no cache,才会跳过缓存;f5发送请求头中会触发协商缓存

性能优化:重排重绘、事件委托、异步无阻塞加载js、懒加载、虚拟列表、缓存、代码分割、雪碧图、减少HTTP请求

  • 编码优化
    • 提高数据读取速度,缓存对象成员值
    • DOM
      • 缓存DOM属性和元素
      • 重排、重绘时,先让元素脱离文档流,操作完毕后再插入文档流,减少重排重绘次数
      • 事件委托
    • 流程控制
      • 避免使用for in
      • 减少迭代
  • 静态资源优化
    • 压缩静态文本?
    • 图片优化
      • 响应式图片
      • 视频替换gif图
  • 交付优化
    • 异步无阻塞加载JS
      • script放底部
      • deferer async
      • 动态创建script标签
      • ajax请求js代码注入页面
    • 懒加载
    • 优先加载关键css
    • 资源提示
      • dns-prefetch
      • preconnect
      • prefetch
      • prerender
      • preload
    • 快速响应的用户界面
      • 骨架屏
      • loading动画
  • 构建优化
    • 预编译
    • 代码分割
    • 服务端渲染
    • import函数导入模块
    • 善用缓存

css3动画和js动画的区别

  • css
    • 浏览器对前者会进行一定的优化
    • 自然降级
  • js
    • 兼容性好
    • 效果丰富

移动端兼容

点击事件有300ms延迟,可以用fastclick解决,或者使用zepto的touch模块

非可点击元素监听click事件,需要设置cursor: pointer

h5底部输入框被键盘遮挡

css动画页面闪白、卡顿,解决:可能地使用合成属性transform和opacity来设计CSS3动画

移动端布局

  • 响应式布局,媒体查询
  • rem,根据font-size来布局
  • 设置viewport中的width
  • vm + rem 对于vm的兼容性,可以使用viewport-units-polyfill解决

1像素问题

  • 物理像素和逻辑像素,之间存在一个比例关系,可以通过window.devicePixelRatio获取,所以设计稿上的1px,在实际上会比较粗
  • 解决方案
    • 媒体查询,根据-webkit-min-device-pixel-ratio的不同,来设置小数像素
    • 用js来获取这个比例,再设置小数像素
    • border-image
    • background-image

腾讯一面总结

发表于 2019-03-12
  • json jsonp

    • json是一种数据格式;
    • jsonp是一种数据调用格式,带callback的json就是jsonp
    • 利用script标签没有跨域限制的“漏洞”来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个script元素,地址指向第三方的API网址,并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),形如:callback({“name”:”hax”,”gender”:”Male”}) 这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。主要是利用了html标签的src属性没有同源限制,也就是支持跨域
  • domready onroad

    • 首先要清楚dom文档加载的步骤为:1.解析html结构;2.加载外部脚本和样式表文件;3解析并执行脚本;4.dom树构建完成;5.加载图片等外部文件;6.页面加载完毕。domready(也叫DOMContentLoaded ),在第4步完成后触发;图片onload是在第5步完成后触发;页面onload是第6步完成后触发。由此可见三者执行顺序为:domready→图片load→页面load。
    • domready和onload事件区别,前者:在DOM文档结构准备完毕后就可以对DOM进行操作;后者:整个document文档(包括图片等加载信息)加载完成后才能对DOM进行操作。关键区别就在于后者需要等待图片等资源加载完毕后才执行
  • js事件(捕获 冒泡)

    • dom2级事件
    • 事件流:从页面接收事件的顺序,主要分为事件冒泡流和事件捕获流
    • 事件冒泡:事件从嵌套层次最深的最具体的元素接收,然后逐级向上传播到不具体的节点;事件捕获则反之
    • 三个阶段:捕获阶段、目标阶段、冒泡阶段
    • 事件处理程序:dom0级、dom2级:addEventListener、removeEventListener

      1
      2
      3
      btn.addEventListener("click", function(){
      alert(this.id);
      }, false);

      true代表在捕获时调用,false代表在冒泡时调用,这样可以添加多个事件处理程序

    • 一般都是将事件处理程序添加到冒泡阶段,兼容性更好
    • 事件委托(事件代理)
  • 作用域链是在定义时还是执行时创建的?

    • 执行环境中所有的变量和函数都保存在变量对象中,由解析器在后台使用
    • 每个函数都有自己的执行环境
    • 当代码在一个环境中执行时,会创建变量对象的一个作用域链,这说明函数定义时没有作用域链存在,只有调用时有
    • 作用域链最前端是当前执行代码的变量对象,如果环境是函数,则变量对象是活动对象
    • 作用:标识符解析
  • 原生ajax post请求

    • XMLHttpRequest对象
    • open方法,接收三个参数:get或post、请求Url、是否异步发送
    • send方法

      1
      2
      3
      4
      5
      6
      7
      xhr.open("get", "example.txt", false);
      xhr.send(null);
      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
      alert(xhr.responseText);
      } else {
      alert("Request was unsuccessful: " + xhr.status);
      }
    • 发送异步请求,需要检测XHR对象的readyState属性,这个属性一变化,就会触发readystatechange事件

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      var xhr = createXHR();
      xhr.onreadystatechange = function(){
      if (xhr.readyState == 4){ // 4代表已经接收到全部响应数据
      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
      alert(xhr.responseText);
      } else {
      alert("Request was unsuccessful: " + xhr.status);
      }
      }
      };
      xhr.open("get", "example.txt", true);
      xhr.send(null);
  • 异步script加载方式

    • 脚本加载会导致DOM构建停止,出现白屏,所以一般都是把脚本放在body标签底部位置进行加载
    • 除了底部加载脚本这个方法,还有其他方法解决阻塞问题?

      • defer属性
        • 渲染文档的时候,异步下载资源,但不会立即执行,会等到所有元素解析完再执行
        • 兼容性问题,只被Internet Explorer 4+和Firefox 3.5+支持,不是理想方案
      • async属性
        • 在渲染文档是异步下载资源
      • defer和async的区别
        • defer按顺序执行,async乱序
        • defer下载完后不会立即执行;而async下载完后会立即执行,因此执行过程中也会阻塞元素渲染
      • 动态脚本加载,是非阻塞Javascript下载中最常用的模式,因为它可以跨浏览器,而且简单易用

        1
        2
        3
        4
        var script = document.createElement ("script");
        script.type = "text/javascript";
        script.src = "file1.js";
        document.body.appendChild(script);
      • 用XHR对象下载代码,并注入到页面

  • 基本类型值 引用类型值

    • undefined null boolean string number object symbol这七种数据类型
    • 基本数据类型是按值访问的,存放在栈内存中
    • 引用类型值是按引用访问的,存放在堆内存中
    • typeof能够返回 undefined null boolean string number object function
    • 如何检测一个数组是数组?
      • instanceof
      • 原型链方式 数组.proto.constructor===Array
      • Object.prototype.toString.call(数组)
      • Array.isArray()
  • 内存泄漏

    • 如果闭包的作用域链中保存着一个HTML 元素,那么就意味着该元素将无法被销毁
    • 需要解除对DOM对象的引用
  • xss跨站脚本

    • 反射型(非持久型)
      • 对于 xss 反射型攻击,主要是诱使用户点击恶意的链接或者访问存在漏洞的内容,可以有如下方式:
        • 攻击者可以将恶意链接直接发送给受信任用户,发送的方式有很多种,比如 email, 网站的私信、评论等
        • 攻击者可以购买存在漏洞网站的广告,将恶意链接插入在广告的链接中
    • 存储型(持久型)——>>>输入检查
      • 将一段恶意代码写在评论中,等待其他用户浏览评论时,就自动执行了js代码(获取cookie,并传输给攻击者的服务器);
    • 基于DOM ——>>>输出检查
      • 通过恶意脚本修改DOM结构
    • 如何防范?
      • HttpOnly 防止劫取 Cookie
      • 输入检查,对用户输入进行检查、过滤和转义
      • 输出检查,在变量输出到html页面时,将其进行编码或转义
  • csrf跨站请求伪造

    • 劫持受信任用户向服务器发送非预期请求
    • 攻击者借助受害者的cookie骗取服务器的信任
    • 涉及到浏览器的cookie策略
      • cookie有两种:会话期cookie和持久性cookie,后者可以指定过期时间
    • 攻击者放了一个链接,这个链接指向一些删除操作,主要目的是改变服务器的数据
    • 如何防范?

      • 验证码
      • referer check

        • 在http请求头中的referer字段,表示该请求的来源地址
        • 对每一个删帖请求,验证其referer值,如果该值指向其他网站,那就有可能是跨站伪请求

          1
          2
          3
          4
          if (req.headers.referer !== '正确的站点地址') {
          res.write('csrf 攻击');
          return;
          }
        • 检查referer,还能防止图片盗链

          • 当referer为空时, 返回正确的图;当referer不为空, 且host命中我的目标网站时, 返回正确的图;当referer不为空, 但host未能命中我的目标网站时, 返回错误的图
      • 添加token验证
        • 基本思路是在请求中添加一些攻击者无法伪造的信息,这些信息也不能存储在cookie中。在请求中添加一个类似随机数的token,服务器建立拦截器来验证

二叉树与二叉查找树

发表于 2018-12-09 | 分类于 数据结构

什么是树?

  • 树由一组以边连接的节点组成

一棵树最上面的节点称为根节点

一个节点下面有多个节点,那这个节点被称为父节点

没有任何子节点的节点称为叶子节点

从一个节点到另一个节点的这一组边被称为路径

以某种顺序访问树中所有节点称为树的遍历

树的层数就是树的深度

每一个节点都有一个与之相关的值,这个值被称为键

二叉树是一种特殊的树,它的特点是子节点的个数不超过两个

二叉查找树是一种特殊的二叉树,特点是较小的值保存在左节点,较大的值保存在右节点

无论是二叉树还是二叉查找树,都是由节点组成的,因此我们首先定义Node节点类

1
2
3
4
5
6
7
8
9
10
function Node(data, left, right){
this.data = data
this.left = left
this.right = right
this.show = show
}

function show(){
return this.data
}

接下来就可以定义一棵二叉查找树了

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
26
27
28
29
30
31
function BST(){
this.root = null
this.insert = insert
this.inOrder = inOrder
}

function insert(data){
let node = new Node(data, null, null)
if(this.root == null){
this.root = node
}else {
let current = this.root
let parent
while(true){
parent = current
if(data < current.data){
current = current.left
if(current == null){
parent.left = node
break
}
}else{
current = current.right
if (current == null) {
parent.right = node
break
}
}
}
}
}

至此,我们已经能够向二叉树中插入节点了,我们还需要能够遍历这棵二叉树(以一定的顺序来显示节点)

遍历二叉树有三种方式:中序,先序,后序。其中,中序按节点键值的升序来遍历;先序则是先访问根节点,再访问左子树和右子树;后序则先访问叶子节点,然后是左子树、右子树、根节点

1
2
// 中序代码如下
function

数据结构篇——集合

发表于 2018-12-09 | 分类于 数据结构

集合中的元素被称为成员,这种数据结构有两个特点:

  • 集合内的成员是无序的
  • 集合内的成员不可重复

在这里我们用数组来实现集合Set类

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
function Set() {
this.dataStore = []
this.add = add
this.remove = remove
this.size = size
this.union = union
this.intersect = intersect
this.subset = subset
this.difference = difference
this.show = show
}

function add(data){
if(this.dataStore.indexOf(data) < 0){
this.dataStore.push(data)
return true
}else {
return false
}
}

function remove(data){
let pos = this.dataStore.indexOf(data)
if(pos > -1) {
this.dataStore.splice(pos, 1)
return true
}else {
return false
}
}

// 判断一个元素是否在集合中
function contains(data){
if(this.dataStore.indexOf(data)>-1){
return true
}else {
return false
}
}

// 合并两个集合
function union(set){
let tempSet = new Set()
for(let i = o; i < this.dataStore.length; i++){
tempSet.add(this.dataStore[i])
}
for(let i = 0; i < set.dataStore.length; ++i){
if(!tempSet.contains(set.dataStore[i])){
tempSet.add(set.dataStore[i])
}
}
return tempSet
}

// 返回两个集合的交集
function intersect(set){
let tempSet = new Set()
for(let i = 0; i < this.dataStore.length; i++){
if(set.contains(this.dataStore[i])){
tempSet.add(this.dataStore[i])
}
}
return tempSet
}

// 返回集合的长度
function size(){
return this.dataStore.length
}

// 判断一个集合是否是另一个集合的子集
function subset(set){
if(this.size() > set.size()){
return false
}else {
for(let i of this.dataStore){
if(!set.contains(i)){
return false
}
}
}
return true
}

// 返回两个集合的补集
function difference(set){
let tempSet = new Set()
for(let i = 0; i < this.dataStore.length; i++){
if(!set.contains(this.dataStore[i])){
tempSet.add(this.dataStore[i])
}
}
return tempSet
}

12…7
陈泳仰

陈泳仰

53 日志
16 分类
17 标签
GitHub E-Mail
© 2017 — 2019 陈泳仰