前端知识点总结

2019-10-07  本文已影响0人  fangtang0101

title: 前端知识点总结
author: 作者
top: false
toc: false
date: 2019-08-19 11:13:48
tags:

  1. var let const 的比较

    • let 是 块级作用域 ,其申明的变量只是在 其块级作用域中 有作用

      块级作用域:可以直接理解为 只在 {} 内生效

      **let 申明的 变量,用 window访问不了,var 申明的,window能访问 **

      {
        let a = 10;
        var b = 1;
      }
      a // ReferenceError: a is not defined.
      b // 1
      

      常见题目:

      var a = [];
      for (var i = 0; i < 10; i++) {
        a[i] = function () {
          console.log(i);
        };
      }
      a[6](); // 10
      
      var a = [];
      for (let i = 0; i < 10; i++) {
        a[i] = function () {
          console.log(i);
        };
      }
      a[6](); // 6
      
  1. 块级作用域有什么用

    1. 避免内部变量 覆盖 替换了 外部作用域的 变量,隔离作用

      匿名函数自执行,相当于起到同样的作用,现在有 {} 块级作用域就不用那么麻烦,很多框架就是这样的

    2. 避免 for循环时 计数的变量 泄露成全局变量,带来困恼

      eg

      var s = 'hello';
      for (var i = 0; i < s.length; i++) {
        console.log(s[i]);
      }
      console.log(i); // 5
      
  1. apply call bind 作用,如何实现

    总结:主要都是为了改变 函数执行 的 this 指向问题

    1. 为什么需要出现这几个 函数

      js中函数 在执行过程中 this 的指向是根据 执行时候 当时的上下文环境 决定的,所有只有在执行的时候,才会知道this 到底指向的是 什么对象

      apply call bind 最终都是为了改变 函数 执行时,this的指向问题

    2. 它们之间的区别

      • applycall g功能用法相似,区别在于

        fn.apply(obj,args)           // args 为数组 会将 args 全部传入 fn函数
        fn.call(obj,arg1,arg2,....)   // call 需要将参数 手动一个一个 传进去
        
        fn.call(obj,...args)        // 当然在 ES6 中 用 ... 的语法 同样可以解决这样的问题,功能就一样了
        
  - `apply call` 与 `bind` 的区别

    **总结:1.返回结果不一样 2.`bind` 可以实现颗粒化**

    1. `apply 与 call` 直接就是调用了 函数(fn 函数立刻执行了)
    2. `bind` 绑定函数,返回结果是一个新的函数(新函数是原函数的一个包装,将this 指向绑定的对象)
    3. `bind` 可以实现颗粒化,绑定时可传入 多个参数,当原函数 调用的时候,会将两次的 参数合并 传入原函数

  - 使用场景

    1. 用来实现 js 中的 **继承**

    2. 对象内置方法的跨对象调用(可以实现将一个对象的内部方法 给 任何 其他不具有此方法的对象调用)

       ```
       Math.max.apply(null,[1,2,4,7])
       Math.max.apply(Math,[1,2,4,7])
       ```
  1. 未解决的问题:

    apply call bind 一起使用的时候要,如何解释...

  2. 防抖和节流

    总结:防抖和节流不是一回事

    1. 防抖和节流的概念的区别

      • 防抖:在一个固定时间间隔内(比如10s),重复执行同一个函数,永远执行最后一个,并以此为时间为基础,未来10s内依旧执行最后的一次 (比喻:等公交)

      • 节流:在一个固定时间间隔内(比如10s),重复执行同一个函数,永远执行一次(第一次),忽略其他调用 (比喻:水龙头滴水)

  1. 防抖和节流如何实现

    • 利用 时间戳,每次执行的时候 对比 上次的时间戳 ,来处理是否要 执行当前的函数执行
    • 利用setTimeOut(时间延时函数), 每次在 执行函数之前,检查 上一次的 延时函数是否还存在(也就是判断上次函数是否已经执行),然后根据自己的逻辑 处理 (可以将上次的 延时函数 重置新的,也可以不执行)
  2. 场景:

    • 游戏领域
    • input 输入的同时 实时搜索结果,多次DOM的渲染,当data 在很短的时候内 ,修改的时候,会不断的渲染 DOM
    • 监听 scrollow 等事件执行函数
  3. 自己实现一个(一定要自己不参照情况下,手打代码)

      // 节流
      // 使用时间戳,比较当前时间 与 上次时间 ,如果 时间间隔 > 间隔时间,执行函数,若  < 时间间隔,什么也不做
      function throttle(fn,wait=80) {
          let timePre = 0;
          return function myFunc(){
              let now = + new Date();
              if(now - timePre > wait){
                  timePre = + new Date();
                  // 1.一定要传入 this,看下面 obj的调用(才能展示出来)
                  fn.apply(this,arguments)
                  // fn(arguments)
              }
          }
      }
      function test1(x,y){
          console.log('x y ....',this);
      }
      let fn1 = throttle(test1);
      fn1('cccc','yyyy');  // 此时内部 this 是window
        let obj ={x:'0000',y:'111111',func:fn1};
        obj.func('1','2'); // 此时内部 this 是 obj
    
  4. 原型、原型链和继承

    问题:还是没有完全懂

    1. 原型 与 原型链

      • 所有对象(引用类型)都有一个 __proto__ 属性 ,值即为 原型(一个普通对象而已)

      • 所有函数都有一个prototype属性,值即为 原型(一个普通对象而已)

      • **对象(引用类型)的 __proto__ === 其构造函数的 prototype **

      • 原型链的顶端是 Object.prototype.__proto__ === null,也就是 null

    **原型链:**当一个对象(引用类型)使用点语法的时候,首先从自己的内部寻找此属性,若没有从其原型(一个普通对象)寻找改属性,若没有,再次从该原型的原型中去寻找,直到顶层 null,若都没有,返回 `undefined`
  1. 继承

    js的继承实际上就是改变 构造函数的 原型(将原型指向 父类的一个实例)

    • js中的继承说明:

      1. js是一门面向对象的语言,但是 js 中没有严格意义的 类 与 实例的说法。而是通过 一个原型 的对象 达到 “继承”的目的。

      所以说 js 是比较另类的语言

      1. ES6 中 开始有了 class let const 等概念
      2. 趋势:更加接近 面向对象语言的 语法与概念 ,也更加严谨
    • 手写一个 js 继承 TODO

  1. 模块化

    根据历史知识来理解与记忆

    **对全局变量的影响 **

    命名的冲突与相互替换

    依赖的管理

    同步与异步 是否预下载,是否预执行

    1. 有哪些模块化,发展流程是什么(演变历史)

      • 起初 js 语言很弱,逻辑主要在 后端,所以没有什么模块的概念 都是 直接 写 function

        污染全局的变量、变量容易被外界改变、管理不方便

      • 匿名函数 + 闭包 典型的是 jQuery 等其他插件

      • node.js的兴起,前端可以没有 模块,但是 后端必须要有 模块 commonJs (nodejs社区创建,开始叫 serverjs)

        var abc = require('xxx') // 导入
        // 导出  是一个对象
        module.export = {
        }
        

        特点:导入是同步的,因为后端加载文件是在本地服务器,所以无所谓

        问题:推广到前端的时候,需要异步,因为前端是通过 网络请求来下来模块的

      • node.js 社区 出现了 分歧,有三个分支

        1. 第一个分支:在原有的commonJs的基础上 做兼容,新增 Transport规范 **Browserify compontes6-module-transpiler等 **

          通过工具 将现有node模块 转成 浏览器能用的模块

        2. 第二个分支:制定了AMD 标准(也就是异步)requestJs

          特点:预先下载、预先执行

        3. 第三个分支:module2.0,算是折中吧,融合上面两个的特点 FlyScript(推广不好,后期自己全部删除了)

          特点:预先下载,懒执行

      • 基于第三个方案的基础上 又融合了很多其他的方案 CMD 国内大牛 淘宝的 玉伯开发 seaJs

        特点:预先下载,懒执行。其他 语法上面的区别

        注意:后期发展 AMD CMD 都有相互兼容对方的优点

      • ES6 算是原生支持 模块化,但是浏览器还没有支持,期待中,目前需要 通过 babel-loader编译

        1. 语法

          // 导出
          export {}
          //导入
          import {x,y} from xx   
          import * as model form xx
          
    2. 特点:

       - `Commonjs` 模块运行时加载,`ES6`模块是编译时就输出接口
       - `Commonjs`输出的为 **值的浅拷贝** ;`ES6`输出的是 **值引用**
  1. 各自的 区别是什么

  2. js 中 异步 (比较大的模块)

    1. js 中异步的概念简述 (js 单线程

      • js 是单线程的,js 代码运行是单线程的
      • 当有耗时操作就会阻碍程序,使得浏览器 假死,所以 异步就出现了,弥补js 没有多线程的缺点
      • 异步基于 事件循环 eventLoop,也就是,只有当 不是异步的代码执行完了,才会 执行 异步代码
  1. 有哪些异步,简述各自的 特点(callback Promise async wait

    • callback 作为 js 实现异步的最基础的手段,使用简单,将函数作为参数传递给另外一个函数,在之后的某个条件下才会触发传入的函数,实现异步

      缺点:会出现回调地狱

    • Promise 为了解决 cb 的 回调地狱问题,链式操作,结构明了

    • async waitPromise 的基础上更加简单,将异步代码 写成 同步的逻辑,更加符合 人的阅读与理解

      基于genertor 与 Promise实现

    • xx

  2. 定时器函数(setTimeut setinterval requestAnimationFrame

    属于原生Js的内置函数,直接实现异步

  3. callback

  4. Promise (手写一个Primise)

  5. Generator

  6. async awit

  1. Event Loop (由 js 异步 延展到 js的 Event Loop)

    1. node 与 浏览器中的 Event Loop 不是一样的,差异在哪里
  2. 浏览器——基础知识

    1. BOM 操作

    2. DOM 操作

      增删改查

    3. 事件(事件绑定与代理

    4. Ajax

    5. 跨域问题

      • 什么是跨域

        同源策略:只允许 同一个 协议 域名 端口相同的网页 请求后端数据(请求已经发出,只是reponse被浏览器拦截)

        为什么:确保安全 (预防CSRF攻击,想象钓鱼网站)

      • 如何解决

        1. jsonP

          利用 <script>标签没有跨域的限制

          缺点:只允许get 请求

          <script>
              function jsonp(data) {
               console.log(data)
           }
          </script>    
          
    2. CORS

       **主要后端设置 http请求的配置即可   允许 指定域名 访问接口**

       `Access-Controll-Allow-origin`

    3. postMessaege

       **用于iframe 嵌套的页面之间相互通信**
  1. 存储问题

    • cookie

      1. 生命周期:一般由 服务端 设置 过期时间,当前 也可以前端js 也可以清除

      2. 存储大小:4k

      3. 说明:主要用于 客户端与服务端通信的,识别用户身份,不建议作为存储使用

      4. 安全参数设置:可以设置不同的参数控制cookie

        • value:尽量用密文 并加密
        • http-only:只允许服务端修改,不能通过js修改,安全
        • secure: 只能在https 协议的请求中 携带
        • same-site:浏览器不能在跨域中携带 cookie
  - localStrong

    1. 生命周期:一直在,除非手动删除
    2. 存储大小:4M

  - sessionStrong

    1. 生命周期:页面关闭 就 消除
    2. 存储大小:4M

  - indexDB

    1. 生命周期:一直在,除非手动删除
    2. 存储大小:很大很大
    3. 说明:就是客户端的一个小型数据库

  - service worker

    service worker 是运行在 浏览器后台的 **独立线程** **必须是https请求**

    主要是为了 **缓存 网络请求**
  1. 缓存问题

    • 缓存位置的优先级(从前到后获取数据)

      1. service worker (上面已经讲过)

      2. Memory cache (内存缓存)

        速度快,持续时间短,随时就没有了

      3. Disk cache

        速度慢,持续时间长,随着进程而释放

      4. Push cache

        http2 的内容,了解即可 缓存时间短,会话结束就没有了

      5. 网络请求

        没有缓存,就自能网络请求

    • 缓存策略 注意:都是通过 HTTP header来设置的

      1. 强缓存

        • Expires:Wed, 22 Oct 2018 08:41:00 GMT(xx之后过期)
        • cache-control:max-age=30(30秒之后过期)
      2. 协议缓存

        当缓存过期,便发送数据的最后获取时间给服务端,服务端判断之后告诉服务器,数据没有变,304,便再次使用之前的缓存

        • Last-modified
        • Etag
      3. 场景使用

        • 频繁变化的文件

          cache-control:no-cache 配合 Last-modified每次校验是否需要跟新

        • html 代码

          cache-control:max-age100000(html代码一般很少修改,只有当html 文件改了,即hash值变了再发起请求,否则很长时间都是用的缓存)

  2. 浏览器——安全问题

    • XSS

      • 说明:注入可执行代码 并执行

        1. 持久性:代码被发送到 后端,后端执行了代码,不小心被 混入执行的 Mysql 的代码,可能影响到数据库
        2. 非持久性:代码发送到网页中并执行,影响程序,评论中写入js函数代码提交
      • 防御:

        1. 转义,将一些敏感的 字符等转义

        2. CSP:也就是白名单通

          • 过http header 设置 Content-Security-Policy

            //只允许加载本站资源
            Content-Security-Policy: default-src ‘self’
            //只允许加载 HTTPS 协议图片
            Content-Security-Policy: img-src https://*
            //允许加载任何来源框架
            Content-Security-Policy: child-src 'none'
            
       - meta 标签设置`<meta http-equiv="Content-Security-Policy">`

       

- CSRF

  - 说明:

    **跨站请求攻击**也就是钓鱼网站

  - 防御:

    1. 设置第三方网站 得不到 cookie  `SameSite`

    2. 封掉第三方网络请求

    3. 每个请求 token 验证

    4. referce  表示请求是从哪个地方发过来的

        

- 点击劫持

  - 说明

    **把目标页面嵌入firame,隐藏部分内容,引导点击**

  - 防御 **http header 设置参数限制  X-Frame-options**

    1. 值为 DENY:页面不允许 以  iframe 的方式展示
    2. 值为 SAMEORIGIN: 相同域名下 可以展示 iframe
    3. 值为ALLOW-FROM:允许指定 来源的网页 可以展示 iframe

- 中间人劫持

  - 说明:

    **一般用公共的Wifi,有可能被劫持**

  - 防御:尽量用 HTTPS
  1. 浏览器——渲染机制

    a. 渲染由浏览器的渲染引擎完成,浏览器还有JS引擎,属于两个线程

    b.火狐是 Gekco 引擎 chorm sarfor 是 Webkit 引擎


    1. DOM 渲染

      • 浏览器将 html 代码 (其实就是一堆字符串)词法分析 打标记
      • 根据标记 转换成 node节点
      • 根据 node 节点 组成 DOM 树
    2. CSSOM 渲染

      • 浏览器根据 Css 代码 转换成 CSSOM 树
    3. 渲染树

      • 将 DOM树 与 CSSOM 树 结合起来,生成 渲染树
      • 根据渲染树 调用 GPU 进行 布局(layout) 显示
    4. 影响渲染的因素与解决办法

      • script 的位置,若在 body 之前,那么当 解析到 JS 代码,渲染便会 暂停 下载 JS 代码
      • 如何避免:
        1. 将 JS 代码 放在 body 之后加载
        2. 将 JS 代码延时 或者 异步加载 defer(下载完立即执行) 和 async(下载完不立即执行)
    5. 重绘与回流

      • 重绘:当改变 DOM 的样式 布局,DOM 会重绘

      • 回流:当改变 DOM 的样式,DOM 会回流(改变了布局)

      • 显然:

        1. 发生回流一定会触发重绘,发生重绘不一定触发回流
        2. 回流比重绘 消耗的资源 更大
6. 如何尽量避免 回流

   - css 层级 **扁平化**(**渲染会从标签由内往外寻找,嵌套层级越少越好**)
   - 尽量 合并多次操作 为 一次 操作 DOM 结构(**减少操作DOM的次数**)
   - **少用table**
   - **达到同样的效果,尽量减少影响布局的属性**,( visibity 代替 diapaly:none)
  1. 性能优化(浏览器+js )

    • 图片加载优化(加载优化

      1. 格式: 大图尽量用 jpeg,小图尽量用 png(base64 压缩)
      2. 小图尽量用 css svg代替
      3. 采用雪碧图
      4. 用CDN ,按需请求所需尺寸的图片(移动端一般用小图,大图浪费)
    • DNS 预解析 dns-prefetch

      <link rel='dns-prefetch' href='xx.com'>
      
    • 预加载

      <link rel='preload' href='xx.com'>
      
    • 预渲染

      <link rel='prerender' href='xx.com'>
      
    • 懒加载

    • 懒执行

      图片懒加载(先用占位图片)

    • CDN

      静态资源尽量使用CDN

    • 节流

      水龙头,比方说3分钟一次,一段时间内,只允许一次事件的发生

      实现:

      1. 使用 setTimeout,若时间未到,则清除之前的 setTimeout
      2. 使用时间戳,时间戳相减,大于间隔时间才执行事件
    • 防抖

      从上次事件发生开始算,一段时间时间内,只允许一次事件发生(注意区别)

  2. webpack 性能优化

    尽量使用高版本(版本高,框架内部做了很多优化),打包 node = production ,内部也有很多优化

    • 缩短打包时间
      1. loader的优化 减少打包的范围
      2. 并行打包 happyPack(js是单线程,将内部任务转换成 并行)
      3. DllPlugin 将特定的库提前单独打成包,此包一般情况行下,很长时间不会变(eg,将Vue 提前打成包)
    • 缩小打包后的体积
      1. 压缩代码,也算节省时间的方式
      2. 按需加载,将不同路由 打包成 几个包,需要用到那个就加载哪个(对首页加载的速度有好处
      3. scope Hosting 分析依赖关系,尽量合并模块到一个函数中
      4. Tree Sharing 分析 并去除 没有用到的代码
  3. HTTP 协议

  4. 设计模式

  5. 框架 Vue

    • 生命周期

      • beforeCreated 无法获取到 props 与 data 的数据
      • created 能够获取到 props 与 data的数据
      • beforeMounted 创建VDOM(虚拟DOM)
      • mounted 将VDOM 转换成 真实的DOM
      • beforeUpdate 组件中数据更新前调用
      • update 组件中数据更新后调用
      • beforeDestroyed 组件销毁前 销毁事件 定时器等操作(否则有内存泄漏问题)
      • destroyed 组件全部销毁
    • 组件之间通信

      • propsemit 父子组件通信
      • v-model 父子间通信
      • $parent$children 父子通信,多层通信
      • provideinject 父子通信 ,多层通信
      • eventBus Vuex 任何通信
    • Vue 底层实现的原理

      definedProperty 对每个属性 进行 set get方法监听,对应的修改DOM结构

      缺点:Vue3.0 为何改成 proxy

      1. 无法监听数组,Vue内部自己实现了 Array的几种方法
- Vue 底层是如何编译的

  - 响应式:根据 data 的变化 改变页面

  - 模板引擎:模板如何被解析(**render函数 vdom**)

    **模板就是字符串->js函数(render函数)->返回vnode(虚拟节点,也就是Vdom)**

  - 渲染:

    **根据vnode 渲染成 真实的节点,用的是专门的库**

- 其余知识点

  1. `computed` 和 `watch` 的异同点

     `computed` **:有缓存,只要依赖的属性如果不变,不会触发**

     `watch`:**只要watch发生变化就执行**

  2. `keep-live` 的使用

     **当组件在页面消失,此组件仍然缓存着,会有两个钩子方法,隐藏于出现**

  3. `data`的值为何 返回 是个函数

     **保证每次创建的组件 数据都是 初始化的值,否则同一个组件创建出来的 公用一个data**

  4. `v-if` 与 `v-show` 的区别

     `v-if`:**false,页面不渲染,DOM不存在**

     `v-show`:**false,页面DOM结构还在,只是隐了而已**

  5. `nextTick` 是什么原理

     **Vue所有的数据变化,最终相应到页面的变化,但内部有一个 事件循环的,在一定事件内才会执行一次,所以当数据发生变化,瞬间又要获取对应的变化DOM是报错的,nextTick事件是所有数据变化对应的DOM 渲染都完成的时候的一个回调函数**

  6. xxx

      

- Vuex

  1. 概念:核心就是**store(仓库)**,存放应用中的**很多状态(state)**,跟全局变量不一样
     - **响应式**,当store 中数据发生变化,那么会相应的很多组件发生变化
     - **commit(mutation)才能修改数据**,这样就能跟踪数据的变化
  2. state(仓库),可以想象成 一个**全局的 data**,注意是**响应式**的,可放在 组件的 computed 里面
  3. getter,**想象成对应的computed(计算属性,针对 state中的属性)**
  4. mutation: 改变state 状态的 **唯一方法**,必须是**同步**
  5. action:类似于 mutation的作用
     - 不是直接改变数据,而是 调用 mutation 改变数据
     - action 可以是异步的
  6. module:**模块化**,当state 数据太多时,可以做分割,每个模块 就是有单独的 store state getter mutation action 等
  1. 框架 React

    1. React 的生命周期

      • componentWillMount 组件将要渲染(第一次)
      • componentDidMount 组件已经渲染(首次)
      • componentWillReceiveProps 接受到父类 props,在调用另一个 渲染器之前
      • shouldComponentUpdate 返回 true false,组件是否要渲染
      • componentWillUpdate 组件即将跟新 ,Dom 渲染之前调用
      • componentDidupdate 组件已经跟新 ,Dom 渲染之后调用
      • componentWillUnmount DOM销毁后,用于清除内存 等
    2. shouldComponentUpdate 有什么用,有什么重要的 场景

      根据自己的实际需求 去 决定 是否需要 重新 渲染(因为重新渲染 是比较耗费资源的)

    3. setState 的方法,是异步还是同步,如何在异步之后 做些其他的操作

      异步操作this.setState({},()=>{页面渲染之后调用})

    4. this.state 和 props 有何异同点

      • props 是从父组件 传递下来的,不可以修改
      • 而state 是组件自身的,可以修改
    5. Virtual DOM 了解吗?在React 中是如何工作的,流程

      • 虚拟DOM,不是真实的DOM。而是一个 js 对象,树状的数据结构,用于描述 真实的DOM节点
      • 如何工作:如果state有改变,那么 先改 虚拟DOM,等到一定的时间,统一 根据 虚拟DOM 与 真实DOM 的对比,只更新 不一样的地方
    6. React 中箭头函数 怎么用

      允许函数绑定上下文,改变函数的this 的对象

      this.onChange.bind(this)

    7. HOC 高阶组件了解吗?

      类似于高阶函数

      将组建作为参数 传入函数,返回一个新的组件,在内部可以对 原始的组件 有很多的 特殊处理

    8. refs 是什么

      返回一个组件的对象,父组件可以拿到 子组件的实例,实现数据交互

    9. keys 有什么作用

      给组件标号,再次渲染的时候,可根据标号,从新排序,而不需要重新渲染

    10. redux 与 VueX

      https://segmentfault.com/a/1190000007753542

  2. xxx

上一篇下一篇

猜你喜欢

热点阅读