javascript整理

闲来无事,把之前的笔记整理一下。

基础知识

变量类型

  • 值类型:a和b相等,改a,b不变 (直接赋值值)
    • undefined string number boolean
  • 引用类型:a和b相等,改a,b变 (赋值地址)
    • object function
  • 强制类型转换
    • 字符串拼接
      • var a=10; var b=100 + '10'//string
    • ==
      • 100=='100'; 0==''; null==undefined //true
    • if
      • if(b=100)//转换为true
    • 逻辑运算符(&,||)
      • 10&&0;''||'abc'; !window.abc//都转换为true或false
  • 问题
    • typeof能得到哪些类型
      • number, string, object, boolean, function, undefiend, symbol (null是object)
      • symbol: 可以生成永不重复的值,可以用一个字符串标记
    • 何时使用===,何时使用==
      • ===:内容相等数据类型也相同的严格模式;==:内容相等数据类型可以不相等
      • 使用==的唯一情况:’’if(obj.a==null){}’’

原型 原型链

  • 构造函数
    • function Foo(name,age) {this.name=name; this.age=age return this} var f = new Foo('ted',20)
    • var a ={}是var a =new Object()的语法糖//数组,函数同理
    • 函数名大写字母开头
  • 原型规则和示例
    • 所有的引用类型(数组对象函数)都具有对象特性,即可自由扩展属性(null除外)
    • 所有的引用类型都有一个__proto__属性,属性值是一个普通对象
    • 所有的函数都有一个prototype属性,属性值也是一个普通的对象
    • __proto__对象指向它的构造函数的prototype对象(完全等于)
    • 当试图得到一个引用类型的某个属性时,如果这个变量本身没有这个属性,那么会去它的__proto__,即它的构造函数的prototype中找
    • 例子:不遍历原型上的属性:if(f.hasOwnProperty(item))
  • 原型链
    • 一个对象,对象自身不存在的属性到它的隐式原型找,它的隐式原型不存的的话,再到它的隐式原型的隐式原型中找
    • Object.prototype指向null,防止死循环
  • instanceof
    • instanceof判断一个函数是否是一个变量的构造函数
    • var f = new Foo('ted') f instanceof Foo//true
    • 判断逻辑:f的__proto__一层层往上,能否对应到Foo.prototype
  • 问题
    • 如何准确判断一个变量是数组
      • var arr = [] arr instanceof Array//true
    • 写一个原型链继承的例子
      • function Animal(){this.eat = function(){console.log('eat')}} function Dog(){this.bark(){console.log('bark')}} Dog.prototype=new Animal() var haski=new Dog() //这个比较low
      • function Elem(id){this.elem=document.getElementById(id)}
        Elem.prototype.html=function(val) {
          var elem=this.elem 
          if(val){
              elem.innerHTML=val
              return this
          } else{ 
              return elem.innerHTML}}</pre> 
        
        Elem.prototype.on=function(type,fn){
          var elem=this.elem
          elem.addEventListener(type,fn)
              </pre>
        
        var div1 = new Elem('div1')
    • 描述new一个对象的过程
      • 创建一个新对象
      • this指向这个新对象
      • 执行构造函数的代码,即对this赋值
      • 返回this

作用域 闭包

  • 执行上下文 代码执行的环境
    • 一段<script>:全局上下文
      • 变量定义->函数申明
    • 一个函数:函数上下文
      • 变量定义->函数申明->this->arguments
  • this
    • this要在执行时才能确认值,定义时无法确认
    • call可以改变this的值:a.fn.call({name:B})
    • 1.作为构造函数执行:指向定义的对象
      function Foo(name) {
      this.name = name}
      var f = new Foo(‘ted’)
    • 2.作为对象属性执行:指向该对象
      var obj = {
      name: ‘A’, printName: function () {console.log(this.name)}}
      obj.printName()
    • 3.作为普通函数执行: 指向window
      function fn() {
      console.log(this)}}
    • 4.call apply bind
      function fn1(name, age) {
      alert(name); console.log(this)}
      fn1(‘ted’,20)//普通函数的this,指向window
      fn1.call({x:100},’ted’,20)//通过call函数改变this,指向{x:100}这个对象
      fn1.apply({x:200}, [‘ted’, 20])//apply和call不同在于参数用数组传递
      //bind:适用于函数表达式 
      var fn2 = function (name, age) {
      alert(name); console.log(this)}
      .bind({y:300})
      fn2('ted',20)//通过bind函数改变this,this也指向{y:300}这个对象
  • 作用域
    • JS没有块级作用域
      • 在函数中定义和赋值的变量可以在函数外使用
      • ES6中加入块级作用域:
        for(let i = 0; i< 10; i++){}
        console.log(i)//报错,let定义的变量有块级作用域,在for中定义的不能在for之外访问
    • JS有函数和全局作用域
      • 定义在函数中的变量,只能在函数中修改
    • 自由变量:当前作用域没有定义的变量,可以在父级作用域中去找
  • 作用域链
    • 当前作用域可访问父级作用域
    • 一个元素的父级作用域是在它定义的时候的作用域,而非执行
  • 闭包
    • 函数作为返回值
    • 函数作为参数传递
    • 闭包中返回的函数,若有自由变量,则向(函数定义时)父作用域寻找
  • 问题

    • 说一下对变量提升的理解
      • 在各个执行上下文中,变量定义+函数声明都会提前
    • 说明this几种不同的使用场景
      • 作为构造函数:指向定义的对象
      • 作为对象属性:指向该对象
      • 作为普通函数:指向window
      • call apply bind: 指向改变的对象
    • 创建10个<a>标签,点击的时候弹出来对应的序号
      *
    • 如何理解作用域
      • 自由变量
      • 作用域链,自由变量的查找
      • 闭包的两个场景
    • 闭包
    • 实际开发中闭包的应用

      • 封装变量,收敛权限

        let isFirstLoad = function () {
          let _list = []
          return function (el) {
              if (_list.indexOf(el) >= 0) {
                  return false
              } else {
                  _list.push(el)
                  return true
              }
          }
        }
        
        let firstLoad = isFirstLoad()
        isFirstLoad(10) //true
        isFirstLoad(10) //false
        isFirstLoad(20) //true
        
        

异步和单线程

  • 什么是异步(对比同步)
    • 同步会阻塞,异步不会,遇到setTimeout会先执行后面的代码
    • 何时使用:有可能发生等待的情况-等待的过程不能阻塞程序运行
  • 前端使用异步的场景
    • 定时任务:setTimeout,setInverral
    • 网络请求:ajax请求,动态加载 (时间不固定)
    • 事件绑定:如点击事件,在不点击的时候不能阻塞程序运行
  • 异步和单线程
    • 单线程:代码一个个排队执行,不能同时干两件事
    • js是单线程,所以在遇到阻塞的情况,要用异步,现将不需要等待的代码执行完,再执行异步代码
  • 问题
    • 同步和异步的区别是什么?分别举一个同步和异步的例子
      • 同步会阻塞代码,异步不会,alert是同步,setTimeout是异步
    • 一个关于setTimeout的笔试题
    • 前端使用异步的场景有哪些?
      • 定时任务-网络请求-时间绑定

补充

  • 日期

          Date.now() //获取时间戳
    
          //2019/09/17/23:41:44
          let dt = new Date()
          dt.getTime() //获取时间戳
          dt.getFullYear() //2019
          dt.getMonth() //8 (0-11)
          dt.getDate() //17 (0-31)
          dt.getHours() //23 (0-23)
          dt.getMinutes() //41 (0-59)
          dt.getSeconds() //44 (0-59) 
    
    
  • Math

    • 获取随机数Math.random()
  • 数组api
    • forEach 遍历所有元素
    • every 判断所有元素是否都符合条件
    • some 判断是否有至少一个元素符合条件
    • sort 排序
    • map 对元素重新组装,生成新数组
    • filter 过滤符合条件的元素
  • 对象api
    • for in
  • 题目

    • 获取2019-07-25格式的日期

        let formatDate = function (dt) {
            if (!dt) {
                dt = new Date()
            }
      
            let year = dt.getFullYear()
            let month = dt.getMonth() + 1
            let date = dt.getDate()
      
            if (month < 10) {
                month = '0' + month
            }
            if (date < 10) {
                date = '0' + date
            }
      
            return year + '-' + month + '-' + date
        }
      
        let dt = new Date()
        console.log(formatDate(dt))
      
    • 获取随机数,要求是长度一致的字符串格式

        //获取长度一致的随机数
        let formatRandom = function () {
            let random = Math.random()
            random = random + '0000000000'
            return random.slice(0, 10)
        }
      
        console.log(formatRandom())
      

JS API

  • JS语法标准(基础知识):ECMA 262标准
  • JS-WEB-API(浏览器):W3C标准
    • DOM操作
    • BOM操作:浏览器操作 获取当前地址 获取屏幕尺寸
    • 事件绑定
    • AJAX请求(包括http协议)
    • 存储
    • 没有规定任何JS基础相关的东西
  • 全面考虑,JS内置的全局函数和对象(浏览器打造)
    • Object,Array,Boolean等
    • window document
    • 所有未定义的全局变量,如navigator.userAgent

DOM操作

  • DOM本质
    • 浏览器拿到html代码后,把html结构化成浏览器可识别以及js可识别的东西,就是dom
    • dom本质是js的对象
  • DOM节点操作

    • 获取dom节点

      
        //获取DOM节点
        //get
        let id1 = document.getElementById('id1') //id
      
        let divs = document.getElementByTagName('div') //元素集合
        let div0 = document.getElementByTagName('div')[0] //元素
      
        let classes = document.getElementsByClassName('class1') //class集合
        let class0 = document.getElementsByClassName('class1')[0] //class
      
        //query
        let id1 = document.querySelector('#id1') //id
      
        let divs = document.querySelectorAll('div') //元素集合
        let div0 = document.querySelector('div') //元素,选择第一个div
        let div0 = document.querySelector('div')[0] //元素,选择第一个div
      
        let classes = document.querySelectorAll('.class0') //class集合
        let class0 = document.querySelector('class0') //class,选择第一个class
        let class0 = document.querySelector('class0')[0] //class,选择第一个class
      
      
    • property

      • js对象中的属性

        //获取attribute
        let p0 = document.quertSelectorAll('p')[0]
        
        console.log(p0.style.width) //获取样式
        p0.style.width = '200px' //修改样式
        console.log(p0.className) //获取class
        p0.className = 'p0' //修改class
        
        console.log(p0.nodeName) //p
        console.log(p0.nodeType) //1 
        
    • attribute

      • HTML文档中 标签的属性

        
        //获取attribute
        let p0 = document.querySelectorAll('p')[0]
        p0.getAttribute('attr1') //获取p0上的attr1属性的值
        p0.getAttribute('attr1', 'abc') //修改属性
        p0.getAttribute('style') //获取style,元素上必须有style才行
        p0.getAttribute('style', 'font-size:30px')
        
        
  • DOM结构操作

    • 新增节点 document.createElement(node)

        //添加新节点
        let div1 = document.getElementById('div1')
        let p1 = documemt.createElement('p')
        div1.appendChild(div1)
        //移动现有节点
        let p2 = document.getElementById('p2')
        div1.appendChild(p2)
      
      
    • 获取父节点 childNode.parentElement

        let div1 = getElementById(div1)
        let parent = div1.parentElement
      
      
    • 获取子节点 .parentNode.childNodes

        let div1 = getElementById(div1)
        let parent = div1.parentElement
      
      
      • .childNodes返回所有节点包括文本和注释节点 .children只返回元素节点
    • 删除节点 parentNode.removeChild(childNode)

        let div1 = getElementById(div1)
        let child = div1.childNodes
        //删除第一个子元素
        div1.removeChild(child[0])
      
  • 问题

    • DOM是哪一种基本数据结构
    • DOM操作的常用API有哪些
      • 获取DOM节点,以及节点的property和attr
      • 获取父节点,子节点
      • 新增,删除,移动节点
    • DOM节点的attr和property有何局别
      • property是js属性的修改和获取
      • attr是对html标签的修改和获取

BOM操作

  • navigator浏览器
    • 判断浏览器类型 userAgent
      var ua = navigator.userAgent
      var isChrome = ua.indexOf(‘Chrome’)
      console.log(isChrome)
  • screen屏幕
    • console.log(screen.width)
      console.log(screen.height)
  • location地址栏信息 拆解url
    •   location.href //url
        location.protocal //协议 http https
        location.host //域名
        location.pathname //路径 /learn/199
        location.search //url ? 后面的字符串
        location.search //url # 后的hash
  • history历史 前进后退

    • history.back
      history.forward
  • 问题

    • 如何检测目标浏览器的类型

        let ua = navigator.userAgent
        let isChrome = ua.indexOf('Chrome')
        console.log(isChrome)
      
      
    • 拆解url的各部分

        location.href //url
        location.protocal //协议 http https
        location.host //域名
        location.pathname //路径 /learn/199
        location.search //url ? 后面的字符串
        location.search //url # 后的hash
      

Ajax

  • XMLHttpRequest

    
      let xhr = new XMLHttpRequest() 
      xhr.open("GET", "/api", "false")
      xhr.onreadystatechange = function () {
          if (xhr.readyState === 4) {
              if (xhr.status === 200) {
                  alert(xhr.responseText)
              }
          }
      }
      xhr.send(null)
    
    
  • 状态码说明

    • readyState == 4 ajax状态码
      • 0-(未初始化)还没有调用send()方法
      • 1-(载入)已调用send()方法,正在发送请求
      • 2-(载入完成)send()方法执行完成,已经接收到全部响应内容
      • 3-(交互)正在解析响应内容
      • 4-(完成)响应内容解析完成,可以在客户端调用了
    • statue == 200 http标准状态码
      • 2xx - 表示成功处理请求。如200
      • 3xx - 需要重定向,浏览器直接跳转
      • 4xx - 客户端请求错误,如404
      • 5xx - 服务端错误
  • 跨域

    • 什么是跨域
    • 可以跨域的三个标签
      • <img src=xxx>
        • 用于打点统计,统计网站可能是其他域
      • <link href=xxx>
        • 可以使用CDN,CDN也是其他域
      • <script src=xxx>
        • 可以使用CDN,CDN也是其他域
        • 可以用于JSONP
    • JSONP 前端

        <!-- jsonp跨域 -->
        <script>
          function callbackFunc (data) {
            alert(data)
        }
      
        </script>
      
        <script src="http://www.baidu.com/api/data.js"></script>
      
      
      • 前端定义一个callback函数,得到信息。再用script标签获取一个跨域的信息,这个信息会调用callback({x:100, y:200})
    • 服务器端设置http header 后端

        //后端通过设置httpheader跨域
        response.setHeader("Access-Control-Allow-Origin", "http://a.com, http://b.com");
        response.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
        response.setHeader("Access-Control-Allow-Methods", "PUT, POST,GET, OPTIONS, DELETE");
        //允许接收跨域的cookie
        response.setHeader("Access-Control-Allow-Credentials", "true");
      
  • 问题

    • 手动编写一个ajax,不依赖第三方库
      • 前面有
    • 跨域的几种实现方式
      • JSONP
      • 服务器端设置http header

事件绑定

  • 通用事件绑定

    
      //通用事件绑定函数
      function bindEvent (elem, type, fn) {
          elem.addEventListener(type, fn)
      }
    
      let a1 = document.getElementById('a1')
      bindEvent(a1, 'click', function (e) {
          e.preventDefault()
          alert('clicked')
      })
    
    
  • 事件冒泡

    • 若底层和父层节点有相同绑定事件,底层业务节点的事件(如点击)会先执行,然后会一层层网上执行,先执行底层的事件,然后上一层的事件,然后…
    • 点击激活弹出激活,点击取消弹出取消
      e.stopPropatation():阻止冒泡)
  • 代理 事件冒泡的应用

    • 点击a标签的元素,会弹出相应文字

      `

      <!DOCTYPE html>




      propogation






    ```

(这里target可以定位到当前点击的元素)
  • 问题
    • 编写一个通用的事件监听函数
    • 描述事件冒泡流程
      • dom树形结构
      • 冒泡
      • 阻止冒泡
      • 应用:代理
    • 对于一个无限下拉加载图片的页面,如何给每个图片绑定事件
      • 使用代理:代码简洁,对浏览器压力小

存储

  • cookie
    • 属于http的东西,本身用于客户端和服务端通信
    • 但是它有本地存储的功能,于是被“借用”
    • 使用document.cookie=...获取和修改即可
    • 限制:
      • 存储量太小,只有4kb
      • 所有http请求都带着,会影响获取资源的效率
      • API简单,需要封装才能用document.coockie
  • sessionStorage和localStorage

    • H5专门为存储而设计,最大容量5M
    • API简单易用,key+value
      • localStorage.setItem(key,value)
        localStorage.getItem(key)
  • 问题

    • 描述一下cookie(h5之前),sessionStorage和localStorage的区别
      • cookie和后两者的区别
        • 容量
        • 是否会携带到ajax请求中
        • API易用性
      • 后两者的区别
        • localStorage不会主动删除,sessionStorage随着每次会话结束会清除,95%的场景存储到localStorage中

开发环境

IDE(写代码的效率)

  • webstorm
  • sublime
  • vscode
  • atom

git 版本管理,多人协作

  • 常用命令
    • git add .
    • git checkout xxx
    • git commit -m ‘xxx’ //提交到本地仓库
    • git push origin master
    • git pull origin master
    • git branch
    • git checkout -b xxx
    • git merge xxx

js模块化

  • 不适用模块化的情况
    • 如果a.js, b.js, c.js, c依赖b,b依赖a,引用的时候必须要按顺序,如果顺序错就会报错
    • 引用的文件的变量必须是全局变量,容易被污染
  • 使用模块化
    • a.js 传递出别人所需要的功能函数,b和a需要哪个函数引用哪个函数
    • 引用的时候直接引用最表层的js文件即可
  • AMD 异步模块定义规范

    • require.js
    • 全局define函数
    • 全局require函数
    • 依赖的js会自动、异步加载

      `
      //util.js
      define(function() {

       return {
           func: function () {
               return 1
           }
       }
      

      })

      //a-utils.js
      define([‘./utils.js’], function(util) {

       return {
           func2: function () {
               return util.func()
           }
       }
      

      })

    ```

*  html用:``<script src="/require.js" data-main="./main.js"></script> ``
*  好处:异步加载,不使用(依赖)就不加载
  • CommonJs

    • nodejs模块化规划,现在被大量用于前端
    • 前端开发依赖的插件和库,都可以用npm中获取
    • 构建工具的高度自动化,使得使用npm的成本非常低
    • CommonJS不会异步加载js,而是同步一次性加载出来

        //util.js
        module.exports = {
            func: function () {
                return 1
            }
        }
      
        //a-util.js
        let util = require('./util.js')
        module.exports = {
            func2: function () {
                return utils()
            }
        }
      
  • AMD和CommonJS的使用场景

    • 需要异步加载,用AMD
    • 使用了npm之后建议使用CommonJs

打包工具

  • webpack

    • 启动一个服务,先全局安装,npm install http-server =g,然后在要访问的页面根目录启动服务 http-server 8080
    • npm init 初始化,完成后多处package.json文件
    • npm install webpack --save -dev 安装webpack
  • 配置webpack

    • 创建webpack.config.js

        var path = require('path')
        var webpack = require('require')
      
        module.exports = {
            context: path.resolve(__dirname, './src'),
            extry: {
                app: './app.js'
            }.
            output: {
                path: path.resolve(__dirname, './dist')
                filename: 'bundle.js'
            }
        }
      
    • 创建src app.js等文件

    • 在package.json scripts里加入”start”: “webpack”,就可以在命令行执行start进行打包输出
  • webpack进行代码压缩:
    • 在config的exports中追加plugins: [new webpack.optimize.UglifyJsPlugin()]
  • webpack的主要作用:
    • 代码合并:合并commonjs的语法规范,否则前端无法识别
    • 代码压缩:保证代码上线

上线回滚的流程

  • 上线的基本流程
    • 将测试完成的代码提交到git版本库的master分支
    • 将当前服务器的代码全部打包并记录版本号,备份
    • 将master分支的代码提交覆盖到线上服务器,生成新版本号
  • 回滚的基本流程
    • 将当前服务器的代码全部打包并记录版本号,备份
    • 将备份的上一个版本号解压,覆盖到线上服务器,并生成新的版本号
  • linux基本命令
    • mkdir
    • ls
    • ll 列表形式的ls
    • pwd
    • cd
    • cd ..
    • rm -rf 文件夹名 //删除当前目录下所有文件
    • vi a.js //创建并进入a.js
      • i //insert
      • : //最下行
      • w //写
      • q //退出
    • cp a1 a2 //创建a2,把a1复制到a2
    • mv a1 f1 //把a1移动到f1文件夹
    • cat a1 //查看当前文件
    • grep ‘2’ a.js //查找a.js中的2

运行环境

页面加载过程

  • 加载资源的形式
    • 输入url(或跳转页面)加载html
    • 加载html中的静态资源
      • <script><img>
  • 加载一个资源的过程
    • 浏览器根据DNS服务器得到域名的IP地址
    • 向这个IP的机器发送http请求
    • 服务器收到、处理并返回http请求(图片,html js代码,)
    • 浏览器得到返回的请求并渲染
  • 浏览器渲染页面的过程
    • 根据HTNL结构生成DOM树
    • 根据CSS生成CSSOM(结构化处理)
    • 将DOM和CSSOM整合成RenderTree(渲染树,每个节点都规定了样式)
    • 根据RenderTree开始渲染和展示
    • 遇到<script>时,会执行并阻塞渲染
  • 题目
    • 从输入url到得到html的详细过程
      • 根据DNS得到域名IP-向该IP发送请求-服务器收到处理返回请求-浏览器得到返回内容
    • window.onload和DOMCotentLoaded的区别
      • onload:页面全部资源加载完,包括图片视频等才会执行
      • CotentLoaded:DOM渲染完即可执行,图片还没有加载完
    • 为什么把css文件放在head中?
      • 因为渲染默认是顺序的,保证在渲染body时候浏览器已经知道对应的样式了
    • 为什么把js放在body最下面?
      • 不会阻塞之前body中html的渲染
      • 保证script能拿到所有的html节点标签

性能优化

  • 基本2点
    • 多使用内存、缓存或者其他方法 -开源
    • 减少CPU计算、减少网络 -节流
  • 加载资源优化
    • 静态资源的压缩合并
      • 合并:将多个js文件合并成一个js
      • 压缩:压缩体积
    • 静态资源缓存
      • 通过连接名称,名称不变的话,浏览器会加载之前同名的缓存
    • 使用CDN让资源加载更快
      • 不同区域的网络优化,上海转到上海的节点等等
    • 使用SSR后端渲染,数据直接输出到HTML中(不同ajax请求数据)
  • 页面渲染优化

    • CSS放前面,JS放后面
    • 懒加载(图片懒加载,下拉加载更多/先用一张模糊的图片代替原图,要用的时候再加载) 什么时候用什么时候加载
    • 减少DOM查询,对DOM查询做缓存
    • 减少DOM操作,多个操作尽量合并在一个执行
      • 先创建一个片段frag=document.createDocumentFragment()
    • 事件节流

      • 间隔一段时间执行一次
      • 如键盘输入,在ns内执行一次事件, 不停的输入,也会在一段时间后输出一次

          //时间戳版
          function throttle(fn, delay) {
              let previous = 0
              return function (args) {
                  let _args = args
                  let _this = this
                  let now = Date.now()
                  if (now-previous > wait) {
                      fn.call(_this, _args)
                      previous = now
                  }
              }
          }
        
    • 事件防抖

      • 超过一段时间不输入,执行一次
      • 防止输入一个就输出一个这样的抖动情况,设置一个延迟,超过这个延迟不执行输入的情况下,才会执行输出。也就是输入一堆,停5ms不输入以后,才会输出

          function debounce (fn, delay) {
              let timeout
              return function (args) {
                  let _this = this
                  let _args = args
                  clearTimeout(timeout)
                  timout = setTimeout(function (_args, _this) {
                      fn.call(_this, _args)
                  }, delay)
              }
          }
        
          //使用防抖
          function print (content) {
              console.log(content)
          }
        
          let input = document.getElementById('text')
          let debounceInput = debounce(print, 100)
          input.addEventListener('keyup', function () {
              debounceAjax(e.target.innerHTML)
          })
        
    • 尽早执行操作(DOMCotentLoaded)

安全性

  • XSS跨站请求攻击
    • 新浪博客写一篇文章,同时偷偷插入一段攻击代码<script>
    • 攻击代码中,获取查看者的cookie,发送到自己的服务器
  • XSS预防
    • 前端替换关键字,例如替换<为&lt;>为&gt
    • 后端替换
  • XSRF跨站请求伪造
    • 你已登录一个购物网站,正在浏览商品
    • 付费接口是xxx.com/pay?id=100但是没有任何验证
    • 你收到一封钓鱼邮件,隐藏着<img src='xxx.com/pay?id=100'>
    • 查看邮件的时候,就悄悄付费了
  • XSRF预防
    • 增加验证流程,如输入指纹、密码、短信验证码
  • 问题
    • 前端安全问题的场景有哪些

面试技巧

  • 简历
    • 简介明了,重点突出项目经历和解决方案
    • 把个人博客放在简历中,并且定期维护更新博客
    • 把个人的开源项目放在简历中,并维护开源项目
    • 不能造假,要保证能力和经历上的造假
  • 谈谈你的缺点
    • 说一下最近正在学的东西,比如我对vue不是很了解,正在学vue.js

面试题

  • window.onload和DOMCotentLoaded的区别
    • onload事件触发:页面上所有dom,样式表,脚本,图片,flash都已经加载完;DOMCotentLoaded:仅dom加载完
  • 如何理解JSON
    • 是一个JS对象,有两个API:
      • JSON.stringify(obj)//将js的对象转换成json字符串
      • JSON.parse('{"a":5}')//json字符串转js对象
    • 是一个数据格式
  • js有哪些内置函数
    • Object
    • Array
    • Boolean
    • Number
    • String
    • Function(以上为构造函数)
    • Date
    • RegExp
    • Error
  • new一个vue对象发生了什么?
    1. 执行this._init()方法,初始化对象:
      • 合并配置options
      • 初始化生命周期
      • 初始化事件中心
      • 初始化渲染
      • 初始化data,props,computed,watcher等
    2. 初始化完成,检查如果有el属性,就调用vm.$mount方法挂载

promise

一种异步解决方案,类似一个容器,包括未来会执行的任务

.then()

参数1为resolve的内容,参数2(可以不要)为reject的内容

.catch()

用于resolve有错误的情况,一般用在.then的最后

.finally()

用于不管promise最后状态如何都执行的操作

.all()

用于将多个promise包装成一个
const p = Promise.all([p1, p2, p3]);

  • 必须等三个都resolve,p才resolve,而有一个reject p就reject
  • 场景:几个任务时间不一样,需要等全部完成才执行下一个任务

.race()

Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
const p = Promise.race([p1, p2, p3])

  • 只要有一个resolve了,就算完成
  • 场景:把异步操作和定时器绑定,如果定时到了异步操作还没完成就报错

.resolve()

将对象转换为promise对象,状态为resolve
let jsPromise = Promise.resolve(para)

  • param:
    • promise对象,直接返回不做修改
    • thenable对象:有then: function(resolve, reject){resolve()}的对象,直接封装,立即执行then
    • 普通对象:直接封装,状态为resolve

.reject()

将对象转换为promise对象,状态为reject

.try()

模拟try代码块