CSS


1. 盒模型

页面渲染时,dom 元素所采用的布局模型。可通过box-sizing进行设置。根据计算宽高的区域可分为:

  • content-box (W3C 标准盒模型)
  • border-box(IE 盒模型)
  • padding-box
  • margin-box (浏览器未实现)

2. BFC

块级格式化上下文,是一个独立的渲染区域,只有Block Box参与,它规定了内部的块级盒子如何布局,且BFC 区域与外部的元素相互隔离。

IE下为 hasLayout,可通过 zoom:1 触发

  • 触发条件(5条):

    • 根元素
    • position: absolute/fixed
    • display: inline-block / table / flex / inline-flex
    • float!==none
    • ovevflow !== visible
  • 规则(6条):

    1. 同一个 BFC 的两个相邻 Box 垂直排列
    2. 同一个 BFC 内部的垂直方向距离由margin决定,同一个 BFC的两个相邻 Box 的 margin 会发生重叠
    3. BFC 中子元素的 margin box 的左边, 与包含块 (BFC) border box的左边相接触 (子元素 absolute 除外)
    4. BFC 的区域不会与 float 的元素区域重叠
    5. 计算 BFC 的高度时,浮动子元素也参与计算
    6. 文字层不会被浮动层覆盖,环绕于周围
  • 应用:

    • 阻止 margin重叠
    • 清除内部浮动
    • 自适应两栏布局
    • 可以阻止元素被浮动元素覆盖
    1. 阻止margin重叠

      • 同一个BFC的两个相邻 的块级Box 的 margin 会发生重叠,破坏三个条件之一即可
    2. 清除浮动(解决高度塌陷:让浮动的子元素可以撑开父级的高度)

      • 原理:计算BFC的高度时,浮动元素也参与计算
      • 开启父元素的BFC
        • overflow:hidden
        • 定位
        • 浮动
    3. 自适应两栏布局

      • 原理:BFC 的区域不会与 float 的元素区域重叠
      • 左侧浮动,右侧开启BFC管理子元素
      #left{width: 200px;background: pink;float: left;}#right{background: deeppink;}
      复制代码
      
    4. 可以阻止元素被浮动元素覆盖

3. 清除浮动

  • 给父级加高度

    • 扩展性不好
  • 开启父级BFC

    • overflow:hidden
    • 定位
    • 浮动
    • ie 6 7底下不支持BFC
  • br标签

    • ie6 不支持
    • 违反了结构 行为 样式相分离的原则
  • 空标签

    • 违反了结构 行为 样式相分离的原则
    • ie6下元素的最小高度为19px
    • 可以尝试给元素的fontsize设为0---> 2px
  • 伪元素 + 开启haslayout

    • 因为ie6 7 下不支持伪元素
    • 所以要额外的去开启haslayout
    /*开启haslayout*/
    .clearfix{*zoom: 1;
    }/*ie 6 7 不支持伪元素*/
    .clearfix:after{content: "";display: block;clear: both;
    }
    复制代码
    

4. 层叠上下文

元素提升为一个比较特殊的图层,在三维空间中 (z轴) 高出普通元素一等。

  • 触发条件

    • 根层叠上下文(html)
    • position
    • css3属性
      • flex
      • transform
      • opacity
      • filter
      • will-change
      • -webkit-overflow-scrolling
  • 层叠等级:层叠上下文在z轴上的排序

    • 在同一层叠上下文中,层叠等级才有意义
    • z-index的优先级最高

[图片上传中...(image-e0759-1554431362414-11)]

<figcaption></figcaption>

5. 居中布局

  • 水平居中

    • 行内元素: text-align: center
    • 块级元素:margin: 0 auto
    • absolute + transform
    • flex + justify-content: center
  • 垂直居中

    • line-height: height
    • absolute + transform
    • flex + align-items: center
    • table
  • 水平垂直居中

    • absolute + transform
    #wrap{position: relative;width: 400px;height: 600px;background: pink;margin: 0 auto;}
    #inner{position: absolute;left: 50%;top: 50%;transform: translate3d(-50%,-50%,0);background: deeppink;}
    复制代码
    
    • flex + justify-content + align-items
  • 图片垂直水平居中

    • 利用vertical-align
    #wrap:after{content: "";display: inline-block;height: 100%;width: 0px;background: pink;vertical-align: middle;
    }
    #wrap img{vertical-align: middle;
    }
    复制代码
    

常用布局

三列布局

  • (1)两边固定 当中自适应
  • (2)当中列要完整显示
  • (3)当中列要优先加载

圣杯布局

  • 使用浮动:搭建完整的布局框架
  • 使用margin 为负值:调整旁边两列的位置(使三列布局到一行上)
  • 使用相对定位:调整旁边两列的位置(使两列位置调整到两头)
  • 完整代码:
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><style type="text/css">*{margin: 0;padding: 0;}body{min-width: 600px;}#header,#footer{height: 20px;text-align: center;border: 1px solid  deeppink;background: gray;}#content{padding: 0 200px;}#content .middle{float: left;width: 100%;background: pink;}#content .left{position: relative;left:-200px;margin-left: -100%;float: left;width: 200px;background: yellow;}#content .right{position: relative;right:-200px;margin-left:-200px;float: left;width: 200px;background: yellow;}.clearfix{*zoom: 1;}.clearfix:after{content: "";display: block;clear: both;}</style></head><body> <div id="header">header</div><div id="content" class="clearfix"><div class="middle">middle</div><div class="left">left</div>        <div class="right">right</div>      </div><div id="footer">footer</div></body>
</html>
复制代码

效果:

[图片上传中...(image-b21e27-1554431362414-10)]

<figcaption></figcaption>

双飞翼布局

双飞翼、圣杯实现的对比:

  • 俩种布局方式都是把主列放在文档流最前面,使主列优先加载。
  • 两种布局方式在实现上也有相同之处,都是让三列浮动,然后通过负外边距形成三列布局。
  • 两种布局方式的不同之处在于如何处理中间主列的位置
    • 圣杯布局是利用父容器的左、右内边距+两个从列相对定位;
    • 双飞翼布局是把主列嵌套在一个新的父级块中利用主列的左、右外边距进行布局调整
  • 双飞翼布局完整代码:
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><style type="text/css">*{margin: 0;padding: 0;}body{min-width: 600px;}/*头部 脚部样式*/#header,#footer{border: 1px solid;background: gray;text-align: center;}/*三列的伪等高布局*/#content .middle,#content .left,#content .right{/*padding-bottom:10000px ;margin-bottom: -10000px;*/height: 50px;line-height: 50px;float: left;}/*双飞翼布局*/#content{overflow: hidden;}#content .middle{width: 100%;background: deeppink;}#content .middle .m_inner{padding: 0 200px;}#content .left,#content .right{background: pink;width: 200px;text-align: center;}#content .left{margin-left: -100%;}#content .right{margin-left: -200px;}</style></head><body><div id="header"><h4>header</h4></div><div id="content"><div class="middle"><div class="m_inner">middle</div></div><div class="left">left</div><div class="right">right</div></div><div id="footer"><h4>footer</h4></div></body>
</html>
复制代码

伪等高布局

解决高度不统一问题 添加代码

#content .left,#content .right,#content .middle{padding-bottom: 10000px;margin-bottom: -10000px;}
复制代码
#content{overflow: hidden; }
复制代码

粘连布局

粘连布局,又称为stick footer布局 如果页面内容不够长的时候,页脚块粘贴在视窗底部;如果内容足够长时,页脚块会被内容向下推送。

[图片上传中...(image-5063be-1554431362414-9)]

<figcaption></figcaption>

[图片上传中...(image-170db6-1554431362414-8)]

<figcaption></figcaption>

  • 总结

      1. footer必须是一个独立的结构,与wrap没有任何嵌套关系
      1. footer要使用margin为负来确定自己的位置
      1. wrap区域必须要被自己的子元素撑开
      1. 如果真的想在wrap区域外添加其他结构,这个结构必须定位
  • 实现代码

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /><title></title><style type="text/css">*{margin: 0;padding: 0;}html,body{height: 100%;}#wrap{min-height: 100%;}#footer{height: 50px;background: pink;line-height: 50px;text-align: center;margin-top: -50px;}#main{text-align: center;padding-bottom: 50px;}</style></head><body><div id="wrap"><div id="main">n <br/>n <br/></div></div><div id="footer">footer</div></body>
</html>
复制代码

6. 选择器优先级

  • !important > 行内样式 > #id > .class/伪类/属性> tag > * > 继承 > 默认
  • 选择器 从右往左 解析

7. link 与 @import 的区别

  • 页面使用css的方式主要有3种:
    • 标签行内引用(内联样式)
    • 内部样式表
    • 外部样式表,其中外部样式引用有link和import两种 link和import都可以对css样式进行外部引用,但它们还是有区别的。
  • link@import区别
    1. 从属关系区别
      • @import是 CSS 提供的语法规则,只有导入样式表的作用;link是HTML提供的标签,功能较多,还可以定义 RSS、rel 连接属性等。
    2. 加载顺序区别
      • 当解析到link时,页面会同步加载所引的 css,而@import所引用的 css 会等到页面加载完才被加载
    3. 兼容性区别
      • @import是 CSS2.1 才有的语法, IE5+ 才能识别;link标签作为 HTML 元素,不存在兼容性问题。
    4. DOM可控性区别
      • link可以使用 js 动态引入,@import不行

8. CSS预处理器(Sass/Less/Postcss)

CSS预处理器的原理: 是将类 CSS 语言通过 Webpack 编译 转成浏览器可读的真正 CSS。在这层编译之上,便可以赋予 CSS 更多更强大的功能,常用功能:

  • 嵌套
  • 变量
  • 循环语句
  • 条件语句
  • 自动前缀
  • 单位转换
  • mixin复用 面试中一般不会重点考察该点,一般介绍下自己在实战项目中的经验即可~

9.CSS动画

transition: 过渡动画

  • transition-property: 属性 -transition-duration: 间隔
  • transition-timing-function: 曲线
  • transition-delay: 延迟
  • 常用钩子: transitionend

animation / keyframes

  • animation-name: 动画名称,对应@keyframes
  • animation-duration: 间隔
  • animation-timing-function: 曲线
  • animation-delay: 延迟
  • animation-iteration-count: 次数
    • infinite: 循环动画
  • animation-direction: 方向
    • alternate: 反向播放
  • animation-fill-mode: 静止模式
    • forwards: 停止时,保留最后一帧
    • backwards: 停止时,回到第一帧
    • both: 同时运用 forwards / backwards
  • 常用钩子: animationend

动画属性

尽量使用动画属性进行动画,能拥有较好的性能表现

  • translate
  • scale
  • rotate
  • skew
  • opacity
  • color

JavaScript


1. 原型 / 构造函数 / 实例

  • 原型(prototype): 一个简单的对象,用于实现对象的 属性继承。原型对象即为当前实例对象的父对象。在 Firefox 和 Chrome 中,每个JavaScript对象中都包含一个__proto__ (非标准)的属性指向它爹(该对象的原型),可通过obj.__proto__进行访问。

    [图片上传中...(image-426744-1554431362402-1)]

    <figcaption></figcaption>

    • 所有函数都有一个特别的属性: prototype : 显式原型属性
    • 所有实例对象都有一个特别的属性: __proto__ : 隐式原型属性
    • 显式原型与隐式原型的关系
      • 函数的prototype: 定义函数时被自动赋值, 默认值是一个空Object对象, 即为原型对象
      • 实例对象的__proto__: 在创建实例对象时被自动添加, 并赋值为构造函数的prototype
      • 对象的隐式原型的值为其对应构造函数的显式原型的值
  • 构造函数: 可以通过new来 新建一个对象 的函数。

  • 实例: 通过构造函数和new创建出来的对象,便是实例。

  • 三者关系: 实例通过__proto__指向原型,原型通过constructor指向构造函数

    [图片上传中...(image-7ff28c-1554431362402-0)]

    <figcaption></figcaption>

Object为例,我们常用的Object便是一个构造函数,因此我们可以通过它构建实例。

// 实例
const o1 = new Object()
复制代码

则此时, 实例为o1构造函数为Object,我们知道,构造函数拥有一个prototype的属性指向原型,因此原型为:

// 原型
const prototype = Object.prototype
复制代码

这里我们可以来看出三者的关系:

实例.__proto__ === 原型原型.constructor === 构造函数构造函数.prototype === 原型复制代码

2.原型链:

别名: 隐式原型链。 原型链是由原型对象组成,所有的实例对象都有 __proto__属性,指向了创建该对象的构造函数的原型,__proto__ 将对象连接起来组成了一个链的结构---->原型链。是一个用来实现继承和共享属性的有限的对象链。

  • 属性查找机制: 当查找对象的属性时,先在自身属性中查找,找到返回,如果实例对象自身不存在该属性,则沿着原型链往上一级查找,找到时则输出,不存在时,则继续沿着原型链往上一级查找,直至最顶级的原型对象Object.prototype,如还是没找到,则输出undefined

  • 属性修改机制: 只会修改实例对象本身的属性,如果不存在,则进行添加该属性,如果需要修改原型的属性时,则可以用: b.prototype.x = 2;但是这样会造成所有继承于该对象的实例的属性发生改变。

  • 原型继承:构造函数的实例对象自动拥有构造函数原型对象的属性(方法),利用的就是原型链。 方法一般定义在原型中, 属性一般通过构造函数定义在对象本身上。

function Person(name, age) {this.name = namethis.age = age}Person.prototype.setName = function (name) {this.name = name}
复制代码
  • Object和Function

    • 函数的显示原型指向的对象默认是空Object实例对象(但Object不满足)
     console.log(Fn.prototype instanceof Object) // trueconsole.log(Object.prototype instanceof Object)// falseconsole.log(Function.prototype instanceof Object) // true
    复制代码
    
    • 所有函数都是Function的实例(包含Function)
     console.log(Function.__proto__===Function.protot  ype)
    复制代码
    
    • Object的原型对象是原型链尽头
      console.log(Object.prototype.__proto__) // null
    复制代码
    

3. 探索instanceof

  • instanceof是如何判断的?
    • 表达式: A instanceof B
    • 如果B函数的显式原型对象在A对象的原型链上, 返回true, 否则返回false
  • Function是通过new自己产生的实例
console.log(Object instanceof Function);
console.log(Object instanceof Object);
console.log(Function instanceof Function);
console.log(Function instanceof Object);
function Foo() {}
console.log(Object instanceof  Foo);
复制代码

[图片上传中...(image-5f02a7-1554431362413-7)]

<figcaption></figcaption>

4. 变量提升与函数提升

  • 变量声明提升

    • 通过var定义(声明)的变量, 在定义语句之前就可以访问到
    • 值: undefined
  • 函数声明提升

    • 通过function声明的函数, 在之前就可以直接调用
    • 值: 函数定义(对象)
  • 变量先提升,函数再提升

5. 执行上下文(EC):

执行上下文(EC): 由js引擎自动创建的对象, 包含对应作用域中的所有变量属性

  • 它包含三个部分:

    • 变量对象(VO)
    • 作用域链(词法作用域)
    • this指向
  • 它的类型:

    • 全局执行上下文
    • 函数执行上下文
    • eval执行上下文
  • 生命周期

    • 全局 : 准备执行全局代码前产生, 当页面刷新/关闭页面时死亡
    • 函数 : 调用函数时产生, 函数执行完时死亡
  • 包含哪些属性:

    • 全局 :
      • var定义的全局变量 ==>undefined
      • 使用function声明的函数 ===>function
      • this ===>window
    • 函数
      • var定义的局部变量 ==>undefined
      • 使用function声明的函数 ===>function
      • this ===> 调用函数的对象, 如果没有指定就是window
      • 形参变量 ===>对应实参值
      • arguments ===>实参列表的伪数组
  • 执行上下文创建和初始化的过程

    • 全局执行上下文

      • 在执行全局代码前将window确定为全局执行上下文
      • 对全局数据进行预处理
        • var定义的全局变量==>undefined, 添加为window的属性
        • function声明的全局函数==>赋值(fun), 添加为window的方法
        • this==>赋值(window)
      • 开始执行全局代码
    • 函数执行上下文

      • 在调用函数, 准备执行函数体之前, 创建对应的函数执行上下文对象
      • 对局部数据进行预处理
        • 形参变量==>赋值(实参)==>添加为执行上下文的属性
        • arguments==>赋值(实参列表), 添加为执行上下文的属性
        • var定义的局部变量==>undefined, 添加为执行上下文的属性
        • function声明的函数 ==>赋值(fun), 添加为执行上下文的方法
        • this==>赋值(调用函数的对象)
      • 开始执行函数体代码

执行上下文栈: 在全局代码执行前,JS引擎就会创建一个栈来存储管理所有的执行上下文对象

  • 代码执行过程:
    • 创建 全局上下文 (global EC)
    • 全局执行上下文 (caller) 逐行 自上而下 执行。遇到函数时,函数执行上下文 (callee) 被push到执行栈顶层
    • 函数执行上下文被激活,成为 active EC, 开始执行函数中的代码,caller 被挂起
    • 函数执行完后,callee 被pop移除出执行栈,控制权交还全局上下文 (caller),继续执行

6. 作用域与作用域链

  • 作用域: 一块代码区域(静态的), 在编码时就确定了, 不会再变化

  • 作用域链: 多个嵌套的作用域形成的由内向外的结构, 用于查找变量

  • 分类:

    • 全局
    • 函数
    • 块作用域(ES6 let)
  • 变量的查找规则

    • 在当前作用域下的执行上下文中查找对应的属性, 如果有直接返回, 否则进入2
    • 在上一级作用域的执行上下文中查找对应的属性, 如果有直接返回, 否则进入3
    • 再次执行2的相同操作, 直到全局作用域, 如果还找不到就抛出找不到的异常
  • 作用

    • 作用域: 隔离变量, 可以在不同作用域定义同名的变量不冲突
    • 作用域链: 查找变量
  • 区别作用域与执行上下文

    • 作用域: 静态的, 编码时就确定了(不是在运行时), 一旦确定就不会变化了
    • 执行上下文: 动态的, 执行代码时动态创建, 当执行结束消失
    • 联系: 执行上下文环境是在对应的作用域中的

7. 闭包

  • 如何产生闭包?

    • 当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时, 就产生了闭包
  • 闭包是什么?

    • 通过chrome工具调试查看得知: 闭包本质是内部函数中的一个对象, 这个对象中包含引用的变量属性
    • 理解一: 闭包是嵌套的内部函数(绝大部分人)
    • 理解二: 包含被引用变量(函数)的对象(极少数人)
    • 注意: 闭包存在于嵌套的内部函数中
  • 产生闭包的条件?

    • 函数嵌套
    • 内部函数引用了外部函数的数据(变量/函数)
  • 常见的闭包

    1. 将函数作为另一个函数的返回值
     function fn1() {var a = 2;function fn2() {a++;console.log(a);}return fn2;}var f = fn1();f();f();
    复制代码
    
    1. 将函数作为实参传递给另一个函数调用
    function showDelay(msg, time) {setTimeout(function () {alert(msg)}, time)}
    showDelay('atguigu', 2000)
    复制代码
    
  • 闭包的作用

    1. 使用函数内部的变量在函数执行完后, 仍然存活在内存中(延长了局部变量的生命周期)
    2. 让函数外部能操作内部的局部变量
  • 闭包的生命周期

    1. 产生: 在嵌套内部函数定义执行完时就产生了(不是在调用)
    2. 死亡: 在嵌套的内部函数成为垃圾对象时
  • 闭包的应用 :

    1. 定义JS模块
      • 具有特定功能的js文件
      • 将所有的数据和功能都封装在一个函数内部(私有的)
      • 只向外暴露一个包信n个方法的对象或函数
      • 模块的使用者, 只需要通过模块暴露的对象调用方法来实现对应的功能
    2. 循环遍历加监听
    3. JS框架(jQuery)大量使用了闭包
  • 闭包缺点

    1. 函数执行完后, 函数内的局部变量没有释放, 占用内存时间会变长,容易造成内存泄露
    • 解决:
      • 能不用闭包就不用
      • 及时释放 : f = null; //让内部函数对象成为垃圾对象
    1. 闭包会在父函数外部,改变父函数内部变量的值。 多个子函数的[[scope]]都是同时指向父级,是完全共享的。因此当父级的变量对象被修改时,所有子函数都受到影响。
    • 解决:
      • 变量可以通过 函数参数的形式 传入,避免使用默认的[[scope]]向上查找
      • 使用setTimeout包裹,通过第三个参数传入
      • 使用 块级作用域,让变量成为自己上下文的属性,避免共享

8. 内存溢出与内存泄露

  • 内存溢出
    • 一种程序运行出现的错误
    • 当程序运行需要的内存超过了剩余的内存时, 就出抛出内存溢出的错误
  • 内存泄露
    • 占用的内存没有及时释放
    • 内存泄露积累多了就容易导致内存溢出
    • 常见的内存泄露:
      • 意外的全局变量
      • 没有及时清理的计时器或回调函数
      • 闭包

9. script 引入方式

  1. html 静态<script>引入
<script src="js/index.js" type="text/javascript"></script>
复制代码
  1. js 动态插入<script>
var scriptElement=document.createElement("script");
scriptElement.src="js/test.js";
(document.getElementsByTagName("head")[0] || document.body).appendChild(scriptElement);
复制代码
  1. <script defer>: 异步加载,元素解析完成后执行
  • 延迟脚本defer属性
  • defer:可选。表示脚本可以延迟到文档完全被解析之后再执行。只对外部脚本文件有效。 相当于告诉浏览器立即下载,但延迟执行
  1. <script async>: 异步加载,但执行时会阻塞元素渲染
  • defer类似,async只适用于外部脚本文件,并告诉浏览器立即下载脚本,但不应妨碍页面的其他操作,比如下载其他资源或等待加载其他脚本。

10. 对象的拷贝

  • 数据类型:数据分为基本的数据类型(String, Number, boolean, Null, Undefined)和对象数据类型

    • 基本数据类型:
      • 特点: 存储的是该对象的实际数据
    • 对象数据类型:
      • 特点: 存储的是该对象在栈中引用,真实的数据存放在堆内存里
  • 复制数据

    • 基本数据类型存放的就是实际的数据,可直接复制

      let number2 = 2;
      let number1 = number2;
      复制代码
      
    • 克隆数据:对象/数组

      • 区别: 浅拷贝/深度拷贝
      • 判断: 拷贝是否产生了新的数据还是拷贝的是数据的引用
      • 知识点:对象数据存放的是对象在栈内存的引用,直接复制的是对象的引用
      let obj = {username: 'kobe'};
      let obj1 = obj; // obj1 复制了obj在栈内存的引用
      复制代码
      
  • 浅拷贝: 拷贝引用,修改拷贝以后的数据影响原数据

    • 直接赋值给一个变量
    • Object.assign()
    • Array.prototype.slice(): 数组浅拷贝
    • Array.prototype.concat(): 数组浅拷贝
  • 深拷贝: 完全拷贝一个新对象,修改拷贝以后的数据不会影响原数据

    • JSON.parse(JSON.stringify(arr/obj)) :数组或对象深拷贝

      • 具有循环引用的对象时,报错
      • 当值为函数undefined、或symbol时,无法拷贝
    • 实现深度克隆:递归进行逐一赋值

<script type="text/javascript">// 复制的对象的方式// 浅度复制let obj = {username: 'kobe', age: 39, sex: {option1: '男', option2: '女'}};let obj1 = obj;console.log(obj1);obj1.sex.option1 = '不男不女'; // 修改复制的对象会影响原对象console.log(obj1, obj);console.log('-----------');// Object.assign();  浅复制let obj2 = {};Object.assign(obj2, obj);console.log(obj2);obj2.sex.option1 = '男'; // 修改复制的对象会影响原对象console.log(obj2, obj);// 深度克隆(复制)function getObjClass(obj) {let result = Object.prototype.toString.call(obj).slice(8, -1);if(result === 'Null'){return 'Null';}else if(result === 'Undefined'){return 'Undefined';}else {return result;}}// for in 遍历数组的时候遍历的是下标let testArr = [1,2,3,4];for(let i in testArr){console.log(i); // 对应的下标索引}// 深度克隆function deepClone(obj) {let result, objClass = getObjClass(obj);if(objClass === 'Object'){result = {};}else if(objClass === 'Array'){result = [];}else {return obj; // 如果是其他数据类型不复制,直接将数据返回}// 遍历目标对象for(let key in obj){let value = obj[key];if(getObjClass(value) === "Object" || 'Array'){result[key] = deepClone(value);}else {result[key] = obj[key];}}return result;}let obj3 = {username: 'kobe',age: 39, sex: {option1: '男', option2: '女'}};let obj4 = deepClone(obj3);console.log(obj4);obj4.sex.option1 = '不男不女'; // 修改复制后的对象不会影响原对象console.log(obj4, obj3);</script> 
复制代码

11. new运算符的执行过程

  • 新生成一个对象
  • 链接到原型: obj.__proto__ = Con.prototype
  • 绑定this:apply
  • 返回新对象(如果构造函数有自己 retrun 时,则返回该值)

12. 代码的复用

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

  • 函数封装
  • 继承
  • 复制extend
  • 混入mixin
    • Mixin模式:将多个类的接口混入另一个类。mix函数将多个对象合成为一个类,使用时,只继承这个类即可。
  • 借用apply/call

13. 继承

在 JS 中,继承通常指的便是 原型链继承,也就是通过指定原型,并可以通过原型链继承原型上的属性或者方法。

  • 最优化: 圣杯模式
 function inherit( Target , Origin){function F();F.prototype = Origin.prototype;Target.prototype = new F();Target.prototype.constructor = Target;  //把Target的构造函数指向归位Target.prototype.uber= Origin.prototype; //为了让我们知道Target真正继承自谁}
复制代码
 var inherit = (function(Target,Origin){var F =function (){} ;return function(Target,Origin){F.prototype = Origin.prototype;Target.prototype = new F();Target.prototype.constructor =  Target;Target.prototype.uber = Origin.prototype;}})()
复制代码
  • 使用 ES6 的语法糖 class / extends

14. 类型转换

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

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

  • +:

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

  • {}.toString() === '[object object]'

  • NaN !== NaN+undefined 为 NaN

15. 类型判断

判断 Target 的类型,单单用 typeof 并无法完全满足,这其实并不是 bug,本质原因是 JS 的万物皆对象的理论。因此要真正完美判断时,我们需要区分对待:

  • 基本类型(null): 使用 String(null)
  • 基本类型(string / number / boolean / undefined) + function: 直接使用 typeof即可
  • 其余引用类型(Array / Date / RegExp Error): 调用toString后根据[object XXX]进行判断
  • 判断封装:
function checkType(Target){return Object.prototype.toString.call(Target).slice(8,-1)
}
复制代码
  • 很稳的判断封装:
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
}
复制代码

16. 模块化

模块化开发在现代开发中已是必不可少的一部分,它大大提高了项目的可维护、可拓展和可协作性。通常,我们 在浏览器中使用 ES6 的模块化支持,在 Node 中使用 commonjs 的模块化支持。

  • 分类:

    • es6: import / export
    • commonjs: require / module.exports / exports
    • amd: require / defined
  • requireimport的区别

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

    • CommonJS

      • Node.js : 服务器端

      • Browserify : 浏览器端 也称为js的打包工具

      • 基本语法:

        • 定义暴露模块 : exports

          exports.xxx = value
          module.exports = value
          复制代码
          

          引入模块 : require

        var module = require('模块名/模块相对路径')
        复制代码
        
      • 引入模块发生在什么时候?

        • Node : 运行时, 动态同步引入
        • Browserify : 在运行前对模块进行编译/转译/打包的处理(已经将依赖的模块包含进来了), 运行的是打包生成的js, 运行时不存在需要再从远程引入依赖模块
    • AMD : 浏览器端

      • require.js
      • 基本语法
        • 定义暴露模块: define([依赖模块名], function(){return 模块对象})

        • 引入模块: require(['模块1', '模块2', '模块3'], function(m1, m2){//使用模块对象})

        • 配置:

          require.config({//基本路径baseUrl : 'js/',//标识名称与路径的映射paths : {'模块1' : 'modules/模块1','模块2' : 'modules/模块2','angular' : 'libs/angular','angular-messages' : 'libs/angular-messages'},//非AMD的模块shim : {'angular' : {exports : 'angular'},'angular-messages' : {exports : 'angular-messages',deps : ['angular']}}
          })
          复制代码
          
    • CMD : 浏览器端

      • sea.js
      • 基本语法
        • 定义暴露模块:

          define(function(require, module, exports){通过require引入依赖模块通过module/exports来暴露模块exports.xxx = value
          })
          复制代码
          
        • 使用模块seajs.use(['模块1', '模块2'])

    • ES6

      • ES6内置了模块化的实现

      • 基本语法

        • 定义暴露模块 : export

          • 暴露一个对象:

            export default 对象
            复制代码
            
          • 暴露多个:

            export var xxx = value1
            export let yyy = value2var xxx = value1
            let yyy = value2
            export {xxx, yyy}
            复制代码
            
        • 引入使用模块 : import

          • default模块:

            import xxx  from '模块路径/模块名'
            复制代码
            
          • 其它模块

            import {xxx, yyy} from '模块路径/模块名'
            import * as module1 from '模块路径/模块名'
            复制代码
            
      • 问题: 所有浏览器还不能直接识别ES6模块化的语法

      • 解决:

        • 使用Babel将ES6--->ES5(使用了CommonJS) ----浏览器还不能直接支行
        • 使用Browserify--->打包处理----浏览器可以运行

17. 防抖与节流

防抖与节流函数是一种最常用的 高频触发优化方式,能对性能有较大的帮助。

  • 防抖 (debounce): 将多次高频操作优化为只在最后一次执行,通常使用的场景是:用户输入,只需再输入完成后做一次输入校验即可。
function debounce(fn, wait, immediate) {let timer = nullreturn function() {let args = argumentslet context = thisif (immediate && !timer) {fn.apply(context, args)}if (timer) clearTimeout(timer)timer = setTimeout(() => {fn.apply(context, args)}, wait)}
}
复制代码

节流(throttle): 每隔一段时间后执行一次,也就是降低频率,将高频操作优化成低频操作,通常使用场景: 滚动条事件 或者 resize 事件,通常每隔 100~500 ms执行一次即可。

function throttle(fn, wait, immediate) {let timer = nulllet callNow = immediatereturn function() {let context = this,args = argumentsif (callNow) {fn.apply(context, args)callNow = false}if (!timer) {timer = setTimeout(() => {fn.apply(context, args)timer = null}, wait)}}
}
复制代码

18. this

由于 JS 的设计原理: 在函数中,可以引用运行环境中的变量。因此就需要一个机制来让我们可以在函数体内部获取当前的运行环境,这便是this

this 引用的规则

  • fn(),这里可以看成 window.fn(),因此 this === window
  • obj.fn(),便是 obj 调用了函数,既函数中的this === obj
  • 以构造函数形式调用时,this为所生成的对象
  • apply,call,bind调用,this为数指定的对象'

三种方式可以手动修改 this 的指向:

  • call: fn.call(target, 1, 2) 第一个参数:想绑定的值;剩下的参数:调用函数的参数
  • apply: fn.apply(target, [1, 2]) 以数组的形式获取参数
  • bind: fn.bind(target)(1,2) 给一个函数永久绑定this
  • 面试题: 区别bind()call()apply()?
    • fn.bind(obj) : 指定函数中的this, 并返回函数
    • fn.call(obj) : 指定函数中的this,并调用函数

19. ES5/ES6/ES7

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

2个新的关键字

  • let / const: 块级作用域、不存在变量提升、暂时性死区、不允许重复声明
  • const: 声明常量,无法修改

变量的解构赋值

  • 将包含多个数据的对象(数组)一次赋值给多个变量
  • 数据源: 对象/数组
  • 目标: {a, b}/[a, b]

字符串扩展

  • 模板字符串
    • 作用: 简化字符串的拼接
    • 模板字符串必须用``
    • 变化的部分使用${xxx}定义
  • contains(str) : 判断是否包含指定的字符串
  • startsWith(str) : 判断是否以指定字符串开头
  • endsWith(str) : 判断是否以指定字符串结尾
  • repeat(count) : 重复指定次数

对象扩展

  • 简化的对象写法
     let name = 'Tom';let age = 12;let person = {name,age,setName (name) {this.name = name;}};
复制代码
  • Object.assign(target, source1, source2..) : 将源对象的属性复制到目标对象上
  • Object.is(v1, v2) : 判断2个数据是否完全相等
  • __proto__属性 : 隐式原型属性

数组扩展

  • Array.from(v): 将伪数组对象或可遍历对象转换为真数组
  • Array.of(v1, v2, v3) : 将一系列值转换成数组
  • find(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素
  • findIndex(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素下标

函数扩展

  • 箭头函数
    • 用来定义匿名函数
    • 基本语法:
      • 没有参数: () => console.log('xxxx')
      • 一个参数: i => i+2
      • 大于一个参数: (i,j) => i+j
      • 函数体不用大括号: 默认返回结果
      • 函数体如果有多个语句, 需要用{}包围
    • 使用场景: 多用来定义回调函数
  • 形参的默认值
    • 定义形参时指定其默认的值
  • rest(可变)参数
    • 通过形参左侧的...来表达, 取代arguments的使用
  • 扩展运算符(...)
    • 可以分解出数组或对象中的数据

class类

  • 用 class 定义类
  • 用 constructor() 定义构造方法(相当于构造函数)
  • 一般方法: xxx () {}
  • extends来定义子类
  • super()来父类的构造方法
  • 子类方法自定义: 将从父类中继承来的方法重新实现一遍
  • js中没有方法重载(方法名相同, 但参数不同)的语法

Set / Map: 新的数据结构

  • 容器: 能保存多个数据的对象, 同时必须具备操作内部数据的方法
    • 任意对象都可以作为容器使用, 但有的对象不太适合作为容器使用(如函数)
  • Set的特点: 保存多个value, value是不重复 ====>数组元素去重
  • Map的特点: 保存多个key--value, key是不重复, value是可以重复的
  • API
    • Set()/Set(arr) //arr是一维数组

    • add(value)

    • delete(value)

    • clear();

    • has(value)

    • size

    • Map()/Map(arr) //arr是二维数组

    • set(key, value)

    • delete(key)

    • clear()

    • has(key)

    • size

for--of循环

可以遍历任何容器

  • 数组
  • 对象
  • 伪/类对象
  • 字符串
  • 可迭代的对象

异步解决方案

Promise

  • Promise的使用与实现

    • 解决回调地狱(回调函数的层层嵌套, 编码是不断向右扩展, 阅读性很差)
    • 能以同步编码的方式实现异步调用
    • 在es6之前原生的js中是没这种实现的, 一些第三方框架(jQuery)实现了promise
    • ES6中定义实现API:
    // 1\. 创建promise对象
    var promise = new Promise(function(resolve, reject){ 
    // 做异步的操作 
    if(成功) { resolve(result);  // 将Promise状态从Pending变为Fullfilled
    } else { reject(errorMsg); // 将Promise状态从Pending变Rejected
    } 
    }) 
    // 2\. 调用promise对象的then()
    promise.then(
    result => console.log(result), //成功的回调
    errorMsg => alert(errorMsg) //失败的回调
    )
    复制代码
    

generator

  • generator:ES6提供的解决异步编程的方案之一,可暂停函数(惰性求值)

    • yield: 暂停代码
    • next(): 继续执行代码
    • 每次返回的是yield后的表达式结果
    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

  • await / async: 是generator的语法糖, babel中是基于promise实现。真正意义上去解决异步回调的问题,同步流程表达异步操作

    async function getUserByAsync(){
    let user = await fetchUser();
    return user;
    }const user = await getUserByAsync()
    console.log(user)
    复制代码
    

20. AST

抽象语法树 (Abstract Syntax Tree),是将代码逐字母解析成树状对象的形式。这是语言之间的转换、代码语法检查,代码风格检查,代码格式化,代码高亮,代码错误提示,代码自动补全等等的基础

21. babel编译原理

  • Babel:广为使用的ES6转码器,将ES6代码转为ES5代码,从而在浏览器和其他环境执行

  • babel编译原理

    • babylon将 ES6/ES7 代码解析成 AST
    • babel-traverse 对 AST 进行遍历转译,得到新的 AST
    • 新 AST 通过 babel-generator 转换成 ES5
  • Babel的包构成

    • 核心包

      • babel-core:babel转译器本身,提供了babel的转译API,如babel.transform等,用于对代码进行转译。像webpack的babel-loader就是调用这些API来完成转译过程的。
      • babylon:js的词法解析器
      • babel-traverse:用于对AST(抽象语法树,想了解的请自行查询编译原理)的遍历,主要给plugin用
      • babel-generator:根据AST生成代码
    • 功能包

      • babel-types:用于检验、构建和改变AST树的节点
      • babel-template:辅助函数,用于从字符串形式的代码来构建AST树节点
      • babel-helpers:一系列预制的babel-template函数,用于提供给一些plugins使用
      • babel-code-frames:用于生成错误信息,打印出错误点源代码帧以及指出出错位置
      • babel-plugin-xxx:babel转译过程中使用到的插件,其中babel-plugin-transform-xxx是transform步骤使用的
      • babel-preset-xxx:transform阶段使用到的一系列的plugin
      • babel-polyfill:JS标准新增的原生对象和API的shim,实现上仅仅是core-js和regenerator-runtime两个包的封装
      • babel-runtime:功能类似babel-polyfill,一般用于library或plugin中,因为它不会污染全局作用域
    • 工具包

      • babel-cli:babel的命令行工具,通过命令行对js代码进行转译
      • babel-register:通过绑定node.js的require来自动转译require引用的js代码文件

22. 函数柯里化

在一个函数中,首先填充几个参数,然后再返回一个新的函数的技术,称为函数的柯里化。通常可用于在不侵入函数的前提下,为函数 预置通用参数,供多次重复调用。

const add = function add(x) {return function (y) {return x + y}
}const add1 = add(1)add1(2) === 3
add1(20) === 21
复制代码

23. 数组(array)

  • map: 对数组每一项运行给定函数,返回函数调用结果组成的新数组

  • forEach: 对数组每一项运行给定函数,无返回值。无法break,可以用try/catch中throw new Error来停止

  • filter: 遍历过滤出一个子数组

  • some: 有一项返回true,则整体为true

  • every: 有一项返回false,则整体为false

  • join: 通过指定连接符生成字符串

  • push / pop: 末尾推入和弹出,改变原数组, 返回推入/弹出项

  • unshift / shift: 头部推入和弹出,改变原数组,返回操作项

  • sort(fn) / reverse: 排序与反转,改变原数组

  • concat: 连接数组,不影响原数组, 浅拷贝

  • slice(start, end): 返回截断后的新数组,不改变原数组

  • splice(start, number, value...): 返回删除元素组成的数组,value 为插入项,改变原数组

  • indexOf / lastIndexOf(value, fromIndex): 查找数组项,返回对应的下标

  • reduce / reduceRight(fn(prev, cur), defaultPrev): 两两执行,prev 为上次化简函数的return值,cur 为当前值(从第二项开始)

  • 数组排序:

arr.sort(
(a,b)=>{return a-b;  //升序return b-a;  //降序
}
)
复制代码
  • 数组乱序:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.sort(function () {return Math.random() - 0.5;
});
复制代码
  • 数组拆解: flat: [1,[2,3]] --> [1, 2, 3]
Array.prototype.flat = function() {return this.toString().split(',').map(item => +item )
}
复制代码

24. JSON对象

  • 作用: 用于在json对象/数组与js对象/数组相互转换
  • JSON.stringify(obj/arr): js对象(数组)转换为json对象(数组)
  • JSON.parse(json): json对象(数组)转换为js对象(数组)

Ajax

  • ajax:异步请求数据的web开发技术

  • 通俗讲有四个步骤:

      1. 创建Ajax核心对象XMLHttpRequest(考虑兼容性)
    var xhr=null;  
    if (window.XMLHttpRequest)  {// 兼容 IE7+, Firefox, Chrome, Opera, Safari  xhr=new XMLHttpRequest();  } else{// 兼容 IE6, IE5 xhr=new ActiveXObject("Microsoft.XMLHTTP");  } 
    复制代码
    
      1. 链接到服务器
      //open(方法,待读取文件名,异步传输)xhr.open(method,url,async);
      复制代码
      
      • method:请求的类型;GET 或 POST
      • url:文件在服务器上的位置
      • async:true(异步)或 false(同步)
      1. 发送请求

        //发送请求
        xhr.send(string);//post请求时才使用字符串参数,否则不用带参数。
        复制代码
        
      • 注意:post请求一定要设置请求头的格式内容
      xhr.open("POST","test.html",true);  
      xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");  
      xhr.send("fname=Henry&lname=Ford");  //post请求参数放在send里面,即请求体
      复制代码
      
      1. 接受返回值
      //同步处理
      document.getElementById("myDiv").innerHTML=xhr.responseText; //获取数据直接显示在页面上
      复制代码
      
      //异步处理
      xhr.onreadystatechange=function()  { if (xhr.readyState==4 &&xhr.status==200)  { document.getElementById("myDiv").innerHTML=xhr.responseText;  }
      } 
      复制代码
      
      • responseText 获得字符串形式的响应数据。
      • responseXML 获得XML 形式的响应数据。
      • 什么是readyState?
        • readyState是XMLHttpRequest对象的一个属性,用来标识当前XMLHttpRequest对象处于什么状态。
        • readyState总共有5个状态值,分别为0~4,每个值代表了不同的含义
          • 0:未初始化 -- 尚未调用.open()方法;
          • 1:启动 -- 已经调用.open()方法,但尚未调用.send()方法;
          • 2:发送 -- 已经调用.send()方法,但尚未接收到响应;
          • 3:接收 -- 已经接收到部分响应数据;
          • 4:完成 -- 已经接收到全部响应数据,而且已经可以在客户端使用了;
      • 什么是status?
        • HTTP状态码

浏览器


1. 跨标签页通讯

不同标签页间的通讯,本质原理就是去运用一些可以 共享的中间介质,因此比较常用的有以下方法:

  • 通过父页面window.open()和子页面postMessage

    • 异步下,通过 window.open('about: blank') 和 tab.location.href = '*'
  • 设置同域下共享的localStorage与监听window.onstorage

    • 重复写入相同的值无法触发
    • 会受到浏览器隐身模式等的限制
  • 设置共享cookie与不断轮询脏检查(setInterval)

  • 借助服务端或者中间层实现

2. 浏览器架构

  • 用户界面
  • 主进程
  • 内核
    • 渲染引擎
    • js引擎: 负责js程序的编译与运行
      • 执行栈
    • 事件触发线程
      • 消息队列
        • 微任务
        • 宏任务
    • 网络异步线程
    • 定时器线程

浏览器结构如下图:

[图片上传中...(image-2a2c0e-1554431362410-6)]

<figcaption></figcaption>

  • 用户界面(User Interface):除了显示请求页面用的浏览器主窗口外,其他部分都属于用户界面,包括地址栏、前进/后退按钮、书签菜单等。
  • 浏览器引擎(Browser engine):查询和操作渲染引擎的接口。
  • 渲染引擎(Rendering engine):负责显示请求的内容。它负责取得网页的内容(HTML、XML、图象等等)、整理信息(例如加入CSS等),以及计算网页的显示方式,并显示在屏幕上。
  • 网络(Networking):网络调用,例如HTTP请求。
  • JavaScript解释器(JavaScriptInterpreter):JavaScript引擎,专门处理JavaScript脚本。
  • 用户界面后端(UI Backend):绘制基本的窗口小部件,比如组合框和窗口。
  • 数据存储(Data Persistence):数据持久层。浏览器在硬盘上存储数据,比如cookie。HTML5定义了网络数据库。

3. 浏览器下事件循环(Event Loop)

事件循环是指: 执行一个宏任务,然后执行清空微任务列表,循环再执行宏任务,再清微任务列表

  • 微任务 microtask(jobs)promise / ajax / Object.observe(该方法已废弃)
  • 宏任务 macrotask(task)setTimout / script / IO / UI Rendering

[图片上传中...(image-af592f-1554431362410-5)]

<figcaption></figcaption>

在事件循环中,用户代理会不断从task队列中按顺序取task执行,每执行完一个task都会检查microtask队列是否为空(执行完一个task的具体标志是函数执行栈为空),如果不为空则会一次性执行完所有microtask。然后再进入下一个循环去task队列中取下一个task执行。

4. 从输入 url 到展示的过程

  • DNS 解析:通过域名找到与之对应的服务器ip

  • TCP 三次握手,建立tcp连接

  • 客户端发送HTTP请求,分析 url,设置请求报文(头,主体)

  • 服务器处理请求

  • 服务器响应请求,返回请求的文件 (html)

  • 浏览器渲染

    • HTML parser --> DOM Tree

      • 标记化算法,进行元素状态的标记
      • dom 树构建
    • CSS parser --> Style Tree

      • 解析 css 代码,生成样式树
    • attachment --> Render Tree

      • 结合 dom树 与 style树,生成渲染树
    • layout: 布局

    • GPU painting: 像素绘制页面

5. 重绘与回流

当元素的样式发生变化时,浏览器需要触发更新,重新绘制元素。这个过程中,有两种类型的操作,即重绘与回流。

  • 重绘(repaint): 当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要UI层面的重新像素绘制,因此 损耗较少

  • 回流(reflow): 当元素的尺寸、结构或触发某些属性时,浏览器会重新渲染页面,称为回流。此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。会触发回流的操作:

    • 页面初次渲染

    • 浏览器窗口大小改变

    • 元素尺寸、位置、内容发生改变

    • 元素字体大小变化

    • 添加或者删除可见的 dom 元素

    • 激活 CSS 伪类(例如::hover)

    • 查询某些属性或调用某些方法

      • clientWidth、clientHeight、clientTop、clientLeft
      • offsetWidth、offsetHeight、offsetTop、offsetLeft
      • scrollWidth、scrollHeight、scrollTop、scrollLeft
      • getComputedStyle()
      • getBoundingClientRect()
      • scrollTo()

回流必定触发重绘,重绘不一定触发回流。重绘的开销较小,回流的代价较高。

最佳实践:

  • css

    • 避免使用table布局
    • 将动画效果应用到position属性为absolutefixed的元素上
  • javascript

    • 避免频繁操作样式,可汇总后统一 一次修改
    • 尽量使用class进行样式修改
    • 减少dom的增删次数,可使用 字符串 或者 documentFragment 一次性插入
    • 极限优化时,修改样式可将其display: none后修改
    • 避免多次触发上面提到的那些会触发回流的方法,可以的话尽量用 变量存住

6. 存储

我们经常需要对业务中的一些数据进行存储,通常可以分为 短暂性存储 和 持久性储存

  • 短暂性的时候,我们只需要将数据存在内存中,只在运行时可用

  • 持久性存储,可以分为 浏览器端 与 服务器端

    • 浏览器:

      • cookie: 通常用于存储用户身份,登录状态等

        • http 中自动携带, 体积上限为 4K, 可自行设置过期时间
      • localStorage / sessionStorage: 长久储存/窗口关闭删除, 体积限制为 4~5M

      • indexDB

    • 服务器:

      • 分布式缓存 redis
      • 数据库

7. Web Worker

现代浏览器为JavaScript创造的 多线程环境。可以新建并将部分任务分配到worker线程并行运行,两个线程可 独立运行,互不干扰,可通过自带的 消息机制 相互通信。

基本用法:

// 创建 worker
const worker = new Worker('work.js');// 向主进程推送消息
worker.postMessage('Hello World');// 监听主进程来的消息
worker.onmessage = function (event) {console.log('Received message ' + event.data);
}
复制代码

限制:

  • 同源限制,不能跨域加载JS
  • 无法使用 document / window / alert / confirm
  • 无法加载本地资源
  • worker内代码不能访问DOM(更新UI)

8. V8垃圾回收机制

垃圾回收: 将内存中不再使用的数据进行清理,释放出内存空间。V8 将内存分成 新生代空间 和 老生代空间。

  • 新生代空间: 用于存活较短的对象

    • 又分成两个空间: from 空间 与 to 空间
    • Scavenge GC算法: 当 from 空间被占满时,启动 GC 算法
    • 存活的对象从 from space 转移到 to space
    • 清空 from space
    • from space 与 to space 互换
    • 完成一次新生代GC
  • 老生代空间: 用于存活时间较长的对象

    • 从 新生代空间 转移到 老生代空间 的条件

      • 经历过一次以上 Scavenge GC 的对象
      • 当 to space 体积超过25%
    • 标记清除算法: 标记存活的对象,未被标记的则被释放

      • 增量标记: 小模块标记,在代码执行间隙执,GC 会影响性能
      • 并发标记(最新技术): 不阻塞 js 执行
    • 压缩算法: 将内存中清除后导致的碎片化对象往内存堆的一端移动,解决内存的碎片化

9. 内存泄露

  • 意外的全局变量: 无法被回收
  • 定时器: 未被正确关闭,导致所引用的外部变量无法被释放
  • 事件监听: 没有正确销毁 (低版本浏览器可能出现)
  • 闭包: 会导致父级中的变量无法被释放
  • dom 引用: dom 元素被删除时,内存中的引用未被正确清空

可用 chrome 中的 timeline 进行内存标记,可视化查看内存的变化情况,找出异常点。

服务端与网络

1. HTTPS/HTTP协议

1.0 协议缺陷:

  • 无法复用链接,完成即断开,重新慢启动和 TCP 3次握手
  • head of line blocking: 线头阻塞,导致请求之间互相影响

1.1 改进:

  • 长连接(默认 keep-alive),复用

  • host 字段指定对应的虚拟站点

  • 新增功能:

    • 断点续传

    • 身份认证

    • 状态管理

    • cache 缓存

      • Cache-Control
      • Expires
      • Last-Modified
      • Etag

2.0:

  • 多路复用
  • 二进制分帧层: 应用层和传输层之间
  • 首部压缩
  • 服务端推送

https: 较为安全的网络传输协议

  • 证书(公钥)
  • SSL 加密
  • 端口 443

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。

HTTPS和HTTP的区别主要如下:

  1. https协议需要到ca申请书,一般免费证书较少,因而需要一定费用。

  2. http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

  3. http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443

  4. http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

  • TCP:

    • 三次握手

    • 四次挥手

    • 滑动窗口: 流量控制

    • 拥塞处理

      • 慢开始
      • 拥塞避免
      • 快速重传
      • 快速恢复
  • 缓存策略: 可分为强缓存 和 协商缓存

    • Cache-Control/Expires: 浏览器判断缓存是否过期,未过期时,直接使用强缓存,Cache-Control的 max-age 优先级高于 Expires

    • 当缓存已经过期时,使用协商缓存

      • 唯一标识方案: Etag(response 携带) & If-None-Match(request携带,上一次返回的 Etag): 服务器判断资源是否被修改,

      • 最后一次修改时间: Last-Modified(response) & If-Modified-Since (request,上一次返回的Last-Modified)

        • 如果一致,则直接返回 304 通知浏览器使用缓存
        • 如不一致,则服务端返回新的资源
    • Last-Modified 缺点:

      • 周期性修改,但内容未变时,会导致缓存失效
      • 最小粒度只到 s, s 以内的改动无法检测到
    • Etag 的优先级高于 Last-Modified

2. 常见状态码

  • 1xx: 接受,继续处理
  • 200: 成功,并返回数据
  • 201: 已创建
  • 202: 已接受
  • 203: 成功,但未授权
  • 204: 成功,无内容
  • 205: 成功,重置内容
  • 206: 成功,部分内容
  • 301: 永久移动,重定向
  • 302: 临时移动,可使用原有URI
  • 304: 资源未修改,可使用缓存
  • 305: 需代理访问
  • 400: 请求语法错误
  • 401: 要求身份认证
  • 403: 拒绝请求
  • 404: 资源不存在
  • 500: 服务器错误

3. get / post

  • get: 缓存、请求长度受限、会被历史保存记录
    • 无副作用(不修改资源),幂等(请求次数与资源无关)的场景
  • post: 安全、大数据、更多编码类型 两者详细对比如下图:

[图片上传中...(image-93864c-1554431362410-4)]

<figcaption></figcaption>

4. Websocket

Websocket 是一个 持久化的协议, 基于 http , 服务端可以 主动 push

  • 兼容:

    • FLASH Socket
    • 长轮询: 定时发送 ajax
    • long poll: 发送 --> 有消息时再 response
  • new WebSocket(url)

  • ws.onerror = fn

  • ws.onclose = fn

  • ws.onopen = fn

  • ws.onmessage = fn

  • ws.send()

5. TCP三次握手

建立连接前,客户端和服务端需要通过握手来确认对方:

  • 客户端发送 syn(同步序列编号) 请求,进入 syn_send 状态,等待确认
  • 服务端接收并确认 syn 包后发送 syn+ack 包,进入 syn_recv 状态
  • 客户端接收 syn+ack 包后,发送 ack 包,双方进入 established 状态

6. TCP四次挥手

  • 客户端 -- FIN --> 服务端, FIN—WAIT
  • 服务端 -- ACK --> 客户端, CLOSE-WAIT
  • 服务端 -- ACK,FIN --> 客户端, LAST-ACK
  • 客户端 -- ACK --> 服务端,CLOSED

7. Node 的 Event Loop: 6个阶段

  • timer 阶段: 执行到期的setTimeout / setInterval队列回调

  • I/O 阶段: 执行上轮循环残流的callback

  • idle, prepare

  • poll: 等待回调

      1. 执行回调
      1. 执行定时器
      • 如有到期的setTimeout / setInterval, 则返回 timer 阶段 -如有setImmediate,则前往 check 阶段
  • check

    • 执行setImmediate
  • close callbacks

跨域

  • 什么是跨域?

    • 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。
  • 什么是同源策略

    • 同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指协议+域名+端口三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
  • 同源策略限制以下几种行为:

    • 1.) Cookie、LocalStorage 和 IndexDB 无法读取
    • 2.) DOM 和 Js对象无法获得
    • 3.) AJAX 请求不能发送
  • JSONP:

    • 基本思想:网页通过添加一个<script src=‘’>元素,向服务器请求JSON数据(<script> 的src属性获得js代码, 不受同源政策限制)。服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
    • 由于script脚本只可以通过get发送请求,所以jsonp只可以发送get请求
    • 具体做法:使用jQuery封装的Ajax,只需在客户端的Ajax请求的url中加入url?callback=?即可;
    • 服务器端需写入var callback = req.query.callback;返回的value需要封装成json,res.send(callback+'('+json+')')。
 function jsonp(url, jsonpCallback, success) {const script = document.createElement('script')script.src = urlscript.async = truescript.type = 'text/javascript'window[jsonpCallback] = function(data) {success && success(data)}document.body.appendChild(script)
}
复制代码
  • CORS(Cross-Origin Resource Sharing):
    • 跨域资源共享是一份浏览器技术的规范,以避开浏览器的同源策略,是 JSONP 模式的现代版。
    • 思想:使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功或失败。
    • 与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让前端工程师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好;另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS。
    • 设置 CORS:客户端不需要做什么,只需要在服务器端发送一个响应头即可:‘Access-Control-Allow-Origin’;
      • 如若允许所有域访问:Access-Control-Allow-Origin: *;如:header("Access-Control-Allow-Origin: *");
      • 如若只允许指定域访问:Access-Control-Allow-Origin: 域名A;如:header("Access-Control-Allow-Origin: http://www.test2.com");
  • postMessage

安全

  • XSS攻击: (Cross Site Script) ,跨站脚本攻击
    • 注入恶意代码,浏览器可以执行
    • 危害:cookie被窃取,用户未发布内容被泄露
    • 预防:过滤输入和转义输出
      • cookie 设置 httpOnly
      • 转义页面上的输入内容和输出内容
  • CSRF攻击: Cross-site request forgery),跨站请求伪造
    • 攻击者盗用了你的身份,以你的名义发送恶意请求
    • 不被第三方网站访问到用户的 cookie
    • referer:判断 referer 头,如果不是来自本网站的请求,就判定为CSRF攻击。但是该方法只能防御跨站的csrf攻击,不能防御同站的csrf攻击
    • 使用验证码:每一个重要的post提交页面,使用一个验证码,因为第三方网站是无法获得验证码的。还有使用手机验证码,比如转账是使用的手机验证码。
    • 使用token:每一个网页包含一个web server产生的token,提交时,也将该token提交到服务器,服务器进行判断,如果token不对,就判定位CSRF攻击
    • 将敏感操作又get改为post,然后在表单中使用token. 尽量使用post也有利于防御CSRF攻击。

Vue


1. nextTick

在下次dom更新循环结束之后执行延迟回调,可用于获取更新后的dom状态

  • 新版本中默认是microtasksv-on中会使用macrotasks

  • macrotasks任务的实现:

    • setImmediate / MessageChannel / setTimeout

2. 生命周期

  • _init_

    • initLifecycle/Event,往vm上挂载各种属性
    • callHook: beforeCreated: 实例刚创建
    • initInjection/initState: 初始化注入和 data 响应性
    • created: 创建完成,属性已经绑定, 但还未生成真实dom
    • 进行元素的挂载: $el / vm.$mount()
    • 是否有template: 解析成render function
      • *.vue文件:vue-loader会将<template>编译成render function
    • beforeMount: 模板编译/挂载之前
    • 执行render function,生成真实的dom,并替换到dom tree
    • mounted: 组件已挂载
  • update:

    • 执行diff算法,比对改变是否需要触发UI更新

    • flushScheduleQueue

      • watcher.before: 触发beforeUpdate钩子
      • watcher.run(): 执行watcher中的 notify,通知所有依赖项更新UI
    • 触发updated钩子: 组件已更新

  • actived / deactivated(keep-alive): 不销毁,缓存,组件激活与失活

  • destroy:

    • beforeDestroy: 销毁开始
    • 销毁自身且递归销毁子组件以及事件监听
      • remove(): 删除节点
      • watcher.teardown(): 清空依赖
      • vm.$off(): 解绑监听
    • destroyed: 完成后触发钩子

3. 数据响应(数据劫持)

数据劫持:vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

看完生命周期后,里面的watcher等内容其实是数据响应中的一部分。数据响应的实现由两部分构成: 观察者( watcher ) 和 依赖收集器( Dep ),其核心是 defineProperty这个方法,它可以 重写属性的 get 与 set 方法,从而完成监听数据的改变。

  • Observe (观察者)观察 props 与 state

    • 遍历 props 与 state,对每个属性创建独立的监听器( watcher )
  • 使用 defineProperty重写每个属性的 get/set(defineReactive

    • get: 收集依赖
      • Dep.depend()
        • watcher.addDep()
    • set: 派发更新
      • Dep.notify()
      • watcher.update()
      • queenWatcher()
      • nextTick
      • flushScheduleQueue
      • watcher.run()
      • updateComponent()

双向数据绑定:www.jianshu.com/p/23180880d…

4. virtual dom 原理实现

  • 创建 dom 树

  • 树的diff,同层对比,输出patchs(listDiff/diffChildren/diffProps)

    • 没有新的节点,返回
    • 新的节点tagName与key不变, 对比props,继续递归遍历子树
      • 对比属性(对比新旧属性列表):
        • 旧属性是否存在与新属性列表中
        • 都存在的是否有变化
        • 是否出现旧列表中没有的新属性
    • tagName和key值变化了,则直接替换成新节点
  • 渲染差异

    • 遍历patchs, 把需要更改的节点取出来
    • 局部更新dom

5. Proxy 相比于 defineProperty 的优势

  • 数组变化也能监听到
  • 不需要深度遍历监听
let data = { a: 1 }
let reactiveData = new Proxy(data, {get: function(target, name){// ...},// ...
})
复制代码

6. vue-router

  • mode
    • hash
    • history
  • 跳转
    • this.$router.push()
    • <router-link to=""></router-link>
  • 占位
    • <router-view></router-view>

7. vuex

  • state: 状态中心
  • mutations: 更改状态
  • actions: 异步更改状态
  • getters: 获取状态
  • modules: 将state分成多个modules,便于管理

算法


1. 五大算法

  • 贪心算法: 局部最优解法
  • 分治算法: 分成多个小模块,与原问题性质相同
  • 动态规划: 每个状态都是过去历史的一个总结
  • 回溯法: 发现原先选择不优时,退回重新选择
  • 分支限界法

2. 二分查找

  • 二分查找的前提为:数组、有序。
  • 逻辑为:优先和数组的中间元素比较,如果等于中间元素,则直接返回。如果不等于则取半继续查找。
  • 二分查找,递归实现。
function binarySearch(target,arr,start,end) {var start   = start || 0;var end     = end || arr.length-1;var mid = parseInt(start+(end-start)/2);if(target==arr[mid]){return mid;}else if(target>arr[mid]){return binarySearch(target,arr,mid+1,end);}else{return binarySearch(target,arr,start,mid-1);}return -1;
}
复制代码
  • 不使用递归实现
function binarySearch(target,arr) {var start   = 0;var end     = arr.length-1;while (start<=end){var mid = parseInt(start+(end-start)/2);if(target==arr[mid]){return mid;}else if(target>arr[mid]){start   = mid+1;}else{end     = mid-1;}}return -1;
}
复制代码

3. 基础排序算法

  • 冒泡排序: 比较相邻的两个元素,如果前一个比后一个大,则交换位置(第一轮保证了后面最大)
    function bubleSort(arr) {var len = arr.length;for (let outer = 0 ; outer < len - 1; outer++) {for(let inner = 0; inner <= len - 1 - outer; inner++) {if(arr[inner] > arr[inner + 1]) {[arr[inner],arr[inner+1]] = [arr[inner+1],arr[inner]]}}}return arr;}
复制代码
  • 选择排序: 遍历自身以后的元素,最小的元素跟自己调换位置(第一轮保证了前面最小)
function selectSort(arr) {var len = arr.length;for(let i = 0 ;i < len - 1; i++) {for(let j = i ; j<len; j++) {if(arr[j] < arr[i]) {[arr[i],arr[j]] = [arr[j],arr[i]];}}}return arr
}
复制代码
  • 插入排序: 将元素插入到已排序好的数组中(保证了前i个有序)
function insertSort(arr) {for(let i = 1; i < arr.length; i++) {  //外循环从1开始,默认arr[0]是有序段for(let j = i; j > 0; j--) {  //j = i,将arr[j]依次插入有序段中if(arr[j] < arr[j-1]) {[arr[j],arr[j-1]] = [arr[j-1],arr[j]];} else {break;}}}return arr;
}
复制代码

4. 高级排序算法

  • 快速排序:快速排序是对冒泡排序的一种改进,第一趟排序时将数据分成两部分,一部分比另一部分的所有数据都要小。然后递归调用,在两边都实行快速排序

    • 选择基准值(base),原数组长度减一(基准值),使用 splice
    • 循环原数组,小的放左边(left数组),大的放右边(right数组);
    • concat(left, base, right)
    • 递归继续排序 left 与 right
    function quickSort(arr) {if(arr.length <= 1) {return arr;  //递归出口}var left = [],right = [],current = arr.splice(0,1); for(let i = 0; i < arr.length; i++) {if(arr[i] < current) {left.push(arr[i])  //放在左边} else {right.push(arr[i]) //放在右边}}return quickSort(left).concat(current,quickSort(right));}
    复制代码
    
  • 希尔排序:不定步数的插入排序,插入排序

  • 归并排序

    • 第一步,将数组一分为2,接着将分成的数组继续一分为2,直到长度为1
    • 当递归到了尽头,向上回溯,对于两个有序的数组,我们将它们合并成一个有序数组,从而完成整个归并排序(归并 从下往上)
    function merge(left, right) {
    var result = [];
    while(left.length > 0 && right.length > 0) {if(left[0] < right[0]) {result.push(left.shift());}else {result.push(right.shift());}
    }
    /* 当左右数组长度不等.将比较完后剩下的数组项链接起来即可 */
    return result.concat(left).concat(right);
    }
    function mergeSort(arr){if(arr.length==1) {return arr};var mid=Math.floor(arr.length/2);var left_arr=arr.slice(0,mid),right_arr=arr.slice(mid);return merge(mergeSort(left_arr),mergeSort(right_arr));}
    复制代码
    
  • 堆排序

  • 口诀: 插冒归基稳定,快选堆希不稳定

[图片上传中...(image-d5f7a5-1554431362409-3)]

<figcaption></figcaption>

5. 递归运用:(斐波那契数列): 爬楼梯问题

function cStairs(n) {if(n === 1 || n === 2) {return n;} else {return cStairs(n-1) + cStairs(n-2)}
}
复制代码

6. 数据树

  • 二叉树: 最多只有两个子节点

    • 完全二叉树:二叉树除开最后一层,其他层结点数都达到最大,最后一层的所有结点都集中在左边(左边结点排列满的情况下,右边才能缺失结点)。

    • 满二叉树

      • 深度为 h, 有 n 个节点,且满足 n = 2^h - 1
  • 二叉查找树: 是一种特殊的二叉树,能有效地提高查找效率

    • 小值在左,大值在右
    • 节点 n 的所有左子树值小于 n,所有右子树值大于 n

[图片上传中...(image-438bf6-1554431362409-2)]

<figcaption></figcaption>

  • 遍历节点

    • 前序遍历
        1. 根节点
        1. 访问左子节点,回到 1
        1. 访问右子节点,回到 1
    • 中序遍历
        1. 先访问到最左的子节点
        1. 访问该节点的父节点
        1. 访问该父节点的右子节点, 回到 1
    • 后序遍历
        1. 先访问到最左的子节点
        1. 访问相邻的右节点
        1. 访问父节点, 回到 1
  • 插入与删除节点

7. 天平找次品

有n个硬币,其中1个为假币,假币重量较轻,你有一把天平,请问,至少需要称多少次能保证一定找到假币?

  • 三等分算法:
    • 将硬币分成3组,随便取其中两组天平称量

      • 平衡,假币在未上称的一组,取其回到 1 继续循环
      • 不平衡,假币在天平上较轻的一组, 取其回到 1 继续循环

作者:Precipice君
链接:https://juejin.im/post/5c9996656fb9a070e82c1f4f
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 总结

    参考中高级前端大厂面试秘籍&#xff0c;为你保驾护航金三银四&#xff0c;直通大厂(上)并加以拓展&#xff0c;以供自己复习方便&#xff0c;目前还在学习并不断补充。 CSS 1. 盒模型 页面渲染时&#xff0c;dom 元素所采用的布局模型。可通过box-sizing进行设置。根据计算宽高…...

    2024/4/21 16:01:53
  2. [Unity]《太空射击》开发日记Ep.2(初级篇)

    文章目录前言敌人1脚本预制件敌人1的完善工作触发器式碰撞屏幕边缘检测计算敌人1的飞行角度优化敌人生成器前言 [Unity]《太空射击》开发日记Ep.1&#xff08;入门篇&#xff09; 在上一篇日记中&#xff0c;我从最最基本的一些操作开始&#xff0c;抛弃了美工、架构等等待优化…...

    2024/4/21 16:01:51
  3. 从无到有写一个运维APP(二)

    前言:理论上应该是一周一篇的说&#xff0c;但上一周回湖南浪去了&#xff0c;so~~~~,再者这并不是公司项目&#xff0c;全是自己临时起意&#xff0c;所以业余时间写写~~~更新也许不会太快。 下面是个人的一些思路以及大概每篇文章的内容&#xff0c;也许并不规范&#xff0c;…...

    2024/4/25 10:51:40
  4. 书店

    <!DOCTYPE html> <html ng-app"BookShop"> <head lang"en"><meta charset"UTF-8"><!--必写的一句话--><meta name"viewport" content"widthdevice-width,minimum-scale1.0,maximum-scale1.0,us…...

    2024/4/21 16:01:49
  5. ionic各种模板

    第一个模板 三个页面点击跳转 <!DOCTYPE html> <html ng-app"BShop"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,minimum-scale1.0,maximum-scale1.0,user-scalableno"…...

    2024/4/21 16:01:49
  6. ionic 解析json串 带(路由 侧拉 效果 上拉刷新 下拉加载)

    先上图看效果&#xff1a; 上代码 &#xff0c;一般都是 按顺序上代码的 &#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><meta name"viewport" conte…...

    2024/4/21 16:01:47
  7. 双眼皮做了可以吃鸡肉和花生吗

    ...

    2024/4/27 1:29:52
  8. 武汉美基元潘臻文李力群成都市双眼皮整形

    ...

    2024/4/20 14:40:49
  9. Angular2.js——表单(下)

    这部分是接表单上部分的内容&#xff0c;主要内容有&#xff1a; 1、添加自定义的CSS来提供视觉反馈&#xff1b; 2、显示和隐藏有效性验证的错误信息&#xff1b; 3、使用ngSubmit处理表单提交&#xff1b; 4、禁用表单提交按钮。 添加自定义的CSS来提供视觉反馈 通过ngModel跟…...

    2024/4/20 7:10:03
  10. ng2——表单提交

    angular作为前端框架当然离不开htmlform表单&#xff0c;下边是我在学习的过程中对ng2表单中的应用 首先是声明一个类 export class Hero {constructor(public id:number,public name:string,public power:string,public alertEgo?: string){ } } 然后定义组件&#xff0c;且定…...

    2024/5/1 21:16:16
  11. 哈市哪家医院做双眼皮开眼角好

    ...

    2024/4/20 14:40:43
  12. angularjs php 表单提交,详细分析使用AngularJS编程中提交表单的方式_AngularJS

    在AngularJS出现之前&#xff0c;很多开发者就面对了表单提交这一问题。由于提交表单的方式繁杂而不同&#xff0c;很容易令人疯掉……然而现在看来&#xff0c;依然会让人疯掉。今天&#xff0c;我们会看一下过去使用PHP方式提交的表单&#xff0c;现在如何将其转换为使用Angu…...

    2024/4/20 0:48:57
  13. 哈尔滨平房姐妹花做双眼皮怎么样

    ...

    2024/4/30 17:46:18
  14. 割双眼皮显著北京艺星

    ...

    2024/4/20 14:40:46
  15. ajax怎么模拟请求,如何模拟AJAX请求?

    在端到端测试期间修改scenarios.js以模拟AJAX请求的最简单方法是什么&#xff1f;如何模拟AJAX请求&#xff1f;My Test AngularJS Appangular.module(myApp, [ngResource]);function PlayerController($scope,$resource){$scope.player $resource(player.json).get();}Hello …...

    2024/4/23 19:43:43
  16. 双眼皮增生没有吸收

    ...

    2024/4/21 16:01:45
  17. 什么季节适合割双眼皮增生性疤痕

    ...

    2024/4/21 16:01:45
  18. 杨大平 割哈尔滨医大四院割做双眼皮好评北京艺星

    ...

    2024/4/21 16:01:45
  19. 割了双眼皮多久可以吃炒鸡蛋吗

    ...

    2024/4/21 16:01:43
  20. 长沙有生物焊接双眼皮 鸡肉

    ...

    2024/4/22 7:16:29

最新文章

  1. MySQL —— 库的基本操作

    一、数据库的增删查改 &#xff08;1&#xff09;创建 语句&#xff1a;create database db_name;&#xff08;db_name是自定义的数据库名字&#xff09; &#xff08;2&#xff09;删除 语句&#xff1a;drop database dp_name;&#xff08;dp_name是要被删除的数据库的名字…...

    2024/5/1 22:45:08
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 汽车统一诊断服务UDS协议参考文章和视频

    UDS基础知识介绍-电子发烧友网 【图解UDS】UDS汽车诊断标准协议&#xff08;ISO14229&#xff09;带你入门到精通-有驾 车载测试之UDS诊断协议9&#xff1a;0x27服务&#xff1a;解锁ECU_哔哩哔哩_bilibili UDS诊断的22服务&#xff08;DID读取数据&#xff09;和2E服务&…...

    2024/4/29 23:11:44
  4. 大数据学习十三天(hadhoop基础2)

    一: MapReduce概述(了解) MapReduce是hadoop三大组件之一,是分布式计算组件 Map阶段 : 将数据拆分到不同的服务器后执行Maptask任务,得到一个中间结果 Reduce阶段 : 将Maptask执行的结果进行汇总,按照Reducetask的计算 规则获得一个唯一的结果 我们在MapReduce计算框架的使用过…...

    2024/5/1 13:32:23
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/1 17:30:59
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/30 18:14:14
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/30 18:21:48
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/30 9:43:22
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57