1.介绍
基础知识学习概览
2.开始
3.CSS
块级元素 & 内联元素
- display:block / table ; 有 div h1 h2 table ul ol p 等
- display:inline / inline-block ; 有 span img input button 等
布局
BFC 块级格式化上下文,一块独立渲染区域,内部元素的渲染不会影响边界以外的元素
- float 不是 none
- position 是 absolute 或 fixed
- overflow 不是 visible
- display 是 flex inline-block 等
圣杯布局和双飞翼布局
- 使用float布局
- 两侧使用 margin 负值,以便和中间内容横向重叠
- 防止中间内容被两侧覆盖,一个用padding 一个用 margin
clearfix
.clearfix{
clear: both;
content: '';
display: block;
width: 0;
height: 0;
visibility: hidden;
}
flex 布局
- flex-direction
- justify-content
- align-items
- flex-wrap
- align-self
定位
- relative 依据自身定位
- absolute 依据最近一层的定位元素定位
- absolute relative fixed
- body
- 水平居中
- inline 元素:text-align:center
- block 元素:margin: auto
- absolute 元素:left:50% + margin-left 负值
- 垂直居中
- inline 元素:line-height 的值等于height
- absolute元素:top:50% + margin-top 负值
- absolute元素:transfrom(-50%,-50%)
- absolute元素:top,left,bottom,right = 0 + margin:auto (终极解决方案)
图文样式
- line-height 会继承父元素,设置百分比时,会取 %* 计算后的结果
响应式
- rem 基于根元素的相对单位
- media-query 根据不同的屏幕宽度设置跟元素 font-size
- vw / v
4.变量类型和计算
值类型 和 引用类型
null 特殊引用类型,指针指向为空地址
null == undefined // true
// 除了 == null 之外,其他一律都用 ===
const obj = {x:100}
if(obj.a == null){}
// 这里相当于:
// if (obj.a === null || obj.a === undefined){}
Typeof 能准确判断值类型(除了null),引用类型只能判断 function 和 object
对于
null
来说,虽然它是基本类型,但是会显示object
,这是一个存在很久了的Bug
typeof null // 'object'
typeof NaN // 'number'
typeof dd // 'undefined' dd is not defined
10 && 0 // 10
'' || 'aaa' // 'aaa'
!window.aa // true
在
JS
的最初版本中,使用的是32
位系统,为了性能考虑使用低位存储了变量的类型信息,000
开头代表是对象,然而null
表示为全零,所以将它错误的判断为object
。虽然现在的内部类型判断代码已经改变了,但是对于这个Bug
却是一直流传下来。
深拷贝
function deepClone(obj){
if(typeof(obj)!=='object' || obj==null) return obj;
let copy = obj instanceof Array ? [] : {}
for(let key in obj){
if(obj.hasOwnProperty(key)){
copy[key] = deepClone(obj[key])
}
}
return copy
}
类型判断 instanceof
xiaoming instanceof Student // true
xiaoli instanceof People // true
[] instanceof Array // true
[] instanceof Object // true
{} instanceof Object // true
5.原型和原型链
JS它本身是基于原型继承的语言
hasOwnProperty
实例化对象的隐式原型 === 类(class)的显示原型
- 每个 class 都有显示原型
prototype
- 每个实例都有隐式原型
__proto__
- 实例的
__proto__
指向对应 class 的prototype
xiaoming.__proto__ === Student.prototype
- 现在自身属性和方法查找
- 如果找不到则自动去
__proto__
中查找
- 每个 class 都有显示原型
- 继承
- Student 继承于 People
Student.prototype.__proto__ === People.prototype
简易 Jquery
class jQuery {
constructor(selector) {
const result = document.querySelectorAll(selector)
const length = result.length
for (let i = 0; i < length; i++) {
this[i] = result[i]
}
this.length = length
this.selector = selector
}
get(index) {
return this[index]
}
each(fn) {
for (let i = 0; i < this.length; i++) {
const elem = this[i]
fn(elem)
}
}
on(type, fn) {
return this.each(elem => {
elem.addEventListener(type, fn, false)
})
}
// 扩展很多 DOM API
}
// 插件
jQuery.prototype.dialog = function (info) {
alert(info)
}
// “造轮子”
class myJQuery extends jQuery {
constructor(selector) {
super(selector)
}
// 扩展自己的方法
addClass(className) {
}
style(data) {
}
}
// const $p = new jQuery('p')
// $p.get(1)
// $p.each((elem) => console.log(elem.nodeName))
// $p.on('click', () => alert('clicked'))
6.作用域和闭包
作用域和自由变量
自由变量
- 一个变量在当前作用域没有定义,但被使用了
- 向上级作用域,一层一层向上寻找,直到找到为止
- 如果到全局作用域都没有找到,则报错 xx is not defined
闭包
所有的自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方!!!
function print(fn){
const a = 200
fn()
}
const a = 100
function fn(){
console.log(a)
}
print(fn) // 100
this
常规函数中的 this 取什么样的值是在函数执行时确认,不是在函数定义的时候确认的
对于箭头函数,this
关键字指向的是它当前周围作用域(简单来说是包含箭头函数的常规函数,如果没有常规函数的话就是全局对象),这个行为和常规函数不同。
- 作为普通函数去调用
- 使用 call apply bind(call,apply 直接调用就执行,bind是返回一个新的函数)
- 作为对象方法被调用
- 在class方法中调用
- 箭头函数,箭头函数中的this,是指向它上级作用域的this
bind
// 模拟 bind
Function.prototype.bind1 = function () {
// 将参数拆解为数组
const args = Array.prototype.slice.call(arguments)
// 获取 this(数组第一项)
const t = args.shift()
// fn1.bind(...) 中的 fn1
const self = this
// 返回一个函数
return function () {
return self.apply(t, args)
}
}
function fn1(a, b, c) {
console.log('this', this)
console.log(a, b, c)
return 'this is fn1'
}
const fn2 = fn1.bind1({x: 100}, 10, 20, 30)
const res = fn2()
console.log(res)
7.异步
- 同步和异步的区别是什么
- 同步会阻塞代码执行
- 异步不会阻塞代码执行
- 手写用Promise加载一张图片
- 前端使用异步的场景?
- 网络请求,如ajax 图片加载
- 定时任务,如setTimeout
- 单线程和异步
- 异步 是由单线程这个背景而来的
- JS是单线程语言,只能同时做一件事
- 浏览器和nodejs已支持JS启动进程,如Web Worker
- JS和DOM渲染共用一个线程,因为JS可修改DOM结构
- 遇到等待(如网络请求,定时任务)不能卡住
- 回调callback函数形式
- Callback hell 和 Promise
8.异步进阶
网络请求
定时任务
Event Loop
Promise
- 三种状态:pending、resolved、rejceted
- pending --> resolved 或者 pending --> rejected
- 变化不可逆
then 和 catch 改变状态
- then 正常返回 resolved ,里面有报错则返回 rejected
- catch 正常返回 resolved ,里面有报错则返回 rejected
- resolved 触发后续 then 的回调
- rejected 触发后续 catch 的回调
async / await
- 语法糖
- 异步回调 callback hell
- Promise then catch 链式调用,但也是基于回调函数
- 同步语法,彻底消灭回调函数
- await 必须有 async 包裹
async / await 和 Promise 的关系
执行 async 函数,返回的是 Promise 对象
await 相当于 Promise 的 then
try...catch 可捕获异常,代替了 Promise 的 catch
async function fn(){
return 100;
}
(async function(){
const a = fn();
const b = await fn();
})()
// a 是返回的 promise 100
// b 是 then 返回的值 100
for - of
- 支持异步
宏任务和微任务
- 宏任务:setTimeout、setInterval、Ajax、DOM事件
- 微任务:Promise、async / await
- 微任务执行时机比宏任务要早
event loop 和 DOM 渲染
- call Stack 空闲
- 尝试 DOM 渲染
- 触发 Event Loop
9.DOM
- dom是哪种数据结构
- 树(DOM树)
- dom操作常用API
- 获取dom节点
- attribute ( 在dom标签内的属性 ) 修改html属性,会改变html结构
- property( .style / .className / .nodeName / .nodeType )JS属性操作形式,修改对象属性,不会体现到html结构中
- 两者都有可能引起dom重新渲染
- dom结构操作
- document.creatElement
- document.appendChild ( 如果是现有节点,会移动 )
- p1.parentNode 获取父元素
- p1.childNodes 获取子元素(含text)
- div1.removeChild 删除节点
- 一次性插入多个节点,考虑性能:*createDocumentFragment()、再appendChild
10.BOM
Browser Object Model 浏览器操作相关
- navigator 浏览器信息 (UA)
- navigator.userAgent
- screen 屏幕信息
- screen.width
- screen.height
- location 地址url信息
- location.href : 完整的url
- location.protocol : https:
- location.host : ui.lllllll.top
- location.search : ?a=100&b=200
- location.hash : #anchor
- loaction.pathname : /class/chapt/100.html
- history 前进后退信息
- history.back()
- history.forward()
11.事件
事件绑定
addEventListener
通用的事件绑定函数
function bindEvent(elem,type,fn){
elem.addEventListener(type,fn)
}event.preventDefault() 阻止默认行为
事件冒泡
- event.stopPropagation() 阻止冒泡
- 应用场景:代理 ⬇️
事件代理
- 用e.target获取触发元素
- 用matches来判断是否是期望触发的元素
12.ajax
- new XMLHttpRequest()
var url = "server.php"; //设置请求的地址
var xhr = XMLHttpRequest(); //实例化XMLHttpRequest对象
xhr.open("POST", url, true); //建立间接,要求异步响应
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); //设置为表单方式提交
xhr.onreadystatechange = function () { //绑定响应状态事件监听函数
if (xhr.readyState == 4) { //监听readyState状态
if (xhr.status == 200 || xhr.status == 0) { //监听HTTP状态码
console.log(xhr.responseText); //接收数据
}
}
}
xhr.send(data数据);
Fetch
跨域
- 同源策略:协议,域名,端口
- 图片、css、js 可无视同源策略,可跨域
<img/>
可用于统计打点,可使用第三方统计服务<link/><script>
可使用CDN,CDN一般都是外域<script>
可使用JSONP- CORS - 服务器设置http header
- Access-Control-Allow-Origin
- Access-Control-Allow-Headers
- Access-Control-Allow-Methods
axios
- 支持promise
- XMLHttpRequest 封装
- 支持浏览器和node
13.存储
前端存储
cookie
- 本身用于浏览器和server通讯
- 被『借用』到本地存储来
- 可用document.cookie = 'xxx' 来修改,用 ; 号分割,同key覆盖,不同key追加,这种方式太过简陋
- 最大存 4KB
- 每次请求都会发送到服务端,增加请求数据量
localStorage、sessionStorage
- HTML5专门为存储而设计,最大可存5M
- API简单易用 setItem / getItem
- 不会随着http请求发送出去
- localStorage 数据会永久存储,除非代码或者手动删除
- sessionStorage 数据只存在于当前会话,浏览器关闭就清空
14.http
状态码分类
1xx 服务器收到请求
2xx 请求成功,如200
3xx 重定向,如302
4xx 客户端错误,如404
5xx 服务端错误,如500
常见状态码
200 成功
301 永久重定向(配合location,浏览器自动处理)
302 临时重定向(配合location,浏览器自动处理)
304 资源未被修改
404 资源未找到
403 没有权限
500 服务器错误
504 网关超时
methods
- 传统的methods:GET/POST
- 现在的methods:
- get 获取数据
- post 新建数据
- patch/put 更新数据
- delete 删除数据
- option
Restful API
- 传统API设计:把每个url当做一个功能
- Restful API 设计:把每个url当做一个唯一的资源
- 尽量不用url参数
- 传统API设计:/api/list?page=2
- Restful API 设计:/api/list/2
- 用methods表示操作类型
- 相同url,使用不同methods区分
- 尽量不用url参数
headers
- Request Headers
- Accept 浏览器可接受的数据格式
- Accept-Encoding 浏览器可接收的压缩算法,如gzip
- Accept-Languange 浏览器可接收的语言,如zh-CN
- Connection: keep-alive 一次TCP连接重复使用
- cookie
- Host
- User-Agent(简称UA)浏览器信息
- Content-type 发送数据的格式,如 application/json
- Response Headers
- Content-type 返回数据的格式,如application/json
- Content-length 返回数据的大小,多少字节
- Content-Encoding 返回数据的压缩算法,如gzip
- Set-Cookie
http缓存
强缓存:Cache-Control --> max-age、no-cathe
协商缓存:Last-Modified -->
- Etag / If-None-Match
- 上面两个可以共存,优先使用Etag,Last-Modified只能精确到秒级
命中缓存,返回 304 资源未被修改
关于缓存
- 什么是缓存?
- 为什么需要缓存?
- 加快访问速度
- 哪些资源可以被缓存? 静态资源(js/css/img)
缓存策略(强制缓存+协商缓存)
强制缓存
- headers加Cache-Control : max-age=5184000 (秒)
- 在Response Headers中,控制强制缓存的逻辑,本质上还是服务端控制
- Cache-Control 的值 :
- max-age 最大过期时间
- no-cathe 不用强制缓存,交给服务端,服务端怎么处理,客户端不管
- no-store 不用强制缓存,也不让服务端做缓存,比较彻底
- private 只允许最终用户做缓存
- public 允许中间的路由或代理做缓存
- Expires 同在Response Headers中,同为控制缓存过期,已被 Cache-Control 代替
协商缓存(对比缓存)
服务端缓存策略(服务端来判断一个资源是不是可以被缓存,或者是不是可以用缓存,不是缓存在服务端)
服务端判断客户端资源,是否和服务端资源一样
- 如果一致返回304,否则返回200和最新资源和资源标识
304 资源未被修改
资源标识
- Last-Modified 资源的最后修改时间
- Last-Modified (服务端返回)/ If-Modified-Since (客户端请求带上)
- Etag 资源的唯一标识(一个字符串,类似指纹)
- Etag / If-None-Match
- 会优先使用Etag
- Last-Modified 只能精确到秒级
- 如果资源被重复生成,而内容不变,则Etag更准确
刷新操作方式,对缓存的影响
- 正常操作,输入url跳转,前进后退 (强缓有效,协缓有效)
- 手动刷新,F5 (强缓无效,协缓有效)
- 强制刷新,ctrl+F5 (强缓无效,协缓有效)
15.开发环境
git
git status #查看文件修改状态
git checkout -b dev #新建并切换到该分支
git checkout master #切换分支
git branch #查看分支列表
#分支合并
git fetch #拉取所有分支
抓包
移动端h5
windows:fiddler
mac:Charles
- 手机和电脑连同一个局域网
- 将手机代理到电脑上
- 手机浏览网页,即可抓包
Webpack Babel
模块化
模块化就是一个导入和导出的过程
ES6:
// a.js
export const num = 123;
export function fn(){};
// 导入
import {const} from './a.js'
// b.js default
export default {
name : 'xxx'
}
import n from './b.js'
linux命令
ssh root@192.168.xx.xx #登录
ls #查看文件夹
ls -a #查看所有包含隐藏 -a = all linux下 .开头的都是隐藏文件
ll #看列表形式的文件夹
clear #清屏
mv a.html b.html #修改文件名、移动文件
cp a.js a1.js #拷贝
rm #删文件
rm -rf #删文件夹
touch d.js #新建文件
vi d.js #新建文件并打开 i 编辑插入、 Esc + :wq 保存并退出、:q!不保存直接退出
cat d.js #查看文件
head d.js #打印出文件前面几行
tail d.js #打印末尾几行
grep "babel" package.json #查找文件内容
16.运行环境
从输入url到渲染出页面的整个过程
加载过程
- DNS解析:域名 - > IP地址
- 浏览器根据IP地址向服务器发起 http 请求
- 服务器处理 http 请求,并返回给浏览器
渲染过程
- 根据 HTML 代码生成 DOM Tree
- 根据 CSS 代码生成 CSSOM ( css object model )
- 将 DOM Tree 和 CSSOM 整合成 Render Tree
- 根据 Render Tree 渲染页面
- 遇到
<script>
则暂停渲染
安全
XSS 跨站请求攻击
- 嵌入
<script>
脚本,获取cookie,发送到我的服务器 - 替换特殊字符,如
<
变为<
/>
变为>
XSRF 跨站请求伪造
一封电子邮件,邮件正文隐藏着
<img src="xxx.com/pay?id=100">
,你查看邮件,就帮我购买了这个商品iframe
使用 post 接口
增加验证,例如密码,短信验证码,指纹等
18.总结
强制类型转换和隐式类型转换
- 强制:parseInt 、 parseFloat 、 toString 等
- 隐式:if 、 逻辑运算、==、+ 拼接字符串
全等函数:isEqual
[10,20,30].map(parseInt) => [10,NaN,NaN]
阻止事件冒泡和默认行为
- event.stopPropagation()
- event.preventDefault()
减少DOM操作
- 缓存dom查询结果
- createDocumentFragment() 创建文档片段
JSONP、AJAX
jsonp是通过script标签发送请求,并通过回调函数的形式执行
ajax是通过XMLHttpRequest
函数声明和函数表达式区别
函数声明会提升 function fn(){}
函数表达式没有提升 const fn = function(){}
函数声明会在代码执行前预加载,而函数表达式不会
new Object() 和 Object.create()
- {} 等同于 new Object(),原型 Object.prototype
- Object.create(null) 没有原型
- Object.create({...}) 指定原型
JS实现继承
- class 继承
- prototype 继承
JS捕获异常
try catch
window.onerror
将URL参数解析为JS对象
function queryToObj(){
let res = {}
let query = location.search.substr(1)
query.split('&').forEach(item=>{
let s = item.split('=')
res[s[0]] = s[1]
})
return res
}
function queryToObj(){
let res = {}
const list = new URLSearchParams(location.search)
list.forEach((val,key)=>{
res[key] = val
})
return res
}
Object.assign 不是深拷贝,是浅拷贝
RAF - requestAnimationFrame
- 想要动画流程,更新频率要60帧/s,即16.67ms更新一次视图
- setTimeout 需要手动控制,而RAF浏览器会自动控制
- 后台标签或隐藏 iframe 中,RAF会暂停,而setTImeout依然执行
function animate(){
curWidth = curWidth + 1
if(curWidth < maxWidth){
window.requestAnimationFrame(animate)
}
}
animate()
性能优化的点
原则:多实用内存,缓存,减少计算,减少网络请求
方向:加载页面,页面渲染,页面操作流畅度
前端模块化
全局函数:绑在全局对象上,可能会引发命名冲突,或者数据不安全
NameSpace:封装成对象,减少了全局变量,解决了命名冲突,但是外部可以修改模块内部的数据
匿名函数自调用:通过闭包的方式向外暴露接口,不太好处理模块之间的依赖关系
文件模块化:
- CommonJS
- AMD
- UMD (前两种的兼容)
-