js基础

    • typeof 判断数据类型undefined,number,string,symbol,boolean,object,function,(不能判断null,array)
    • instanceof 检测原型(a.__proto__==b.prototype)
    • f.constructor == F
    • Object.prototype.toString.call('')="[object String]"
  1. _proto_指向创建该对象的构造函数的原型(F.prototype),通过_proto_组成的原型链寻找不属于该对象的属性 prototype是每个函数都有的属性
  2. this 指调用函数的对象,构造函数this绑定里他创建的对象,不会改变,callapply,bind可以改变this指向,箭头函数没有this,他的this取决于外面的函数
  3. Child继承Parent
    • 构造函数在Child里面Parent.call(this),相当于拷贝Parent,浪费内存,不会继承Parent.prototype
    • 原型继承Child.prototype=new Parent() ,引用属性会被共享
    • 组合
      • 属性用在Child里面Parent.call(this)
      • 方法用Child.prototype =Object.create(Parent.prototype);继承Parent方法,(类似写法Child.prototype = new Parent()Child.prototype = Parent.prototype)
      • Child.prototype.constructor = Child;修复Childconstructor 指向
    •   class Child extends Parent{
      
       }
      
  4. let 不能在声明前使用
  5. 非匿名的立即执行函数会把函数名当作该函数的内部只读属性
  6. 闭包是函数A return函数B,函数B使用里A的变量,缓存了这个变量
  7. for循环中的定时可以用let定义i,或者用闭包(function(i){})(i),或者setTimeout的第三个参数i
  8. 基本类型保存在栈,引用类型保存在堆(通过栈中的内存地址找到堆中的值)
    • 浅拷贝:Object.assign({},a) {...a}值解决第一层的拷贝
    • 深拷贝:
      • JSON.parse(JSON.stringify(object))忽略了undefined,函数,循环引用的对象
      • jquery.extend(true,target,object)递归思路
      • new Function("return "+obj.toString())拷贝函数,数组中是对象就递归,递归浅拷贝
    • es6模块化export/import,babel编译成require/exports,异步导入,值引用,实时绑定,导入导出的值都指向同一个内存地址,改变了会有影响,
    • conmmonjs是node中的规范,module.exports暴露, require引入,Browserify 解析,支持动态导入,同步导入,值拷贝,改变了不会影响导入值
  9. 
    • 防抖,防二次点击,边输入边搜索
      • button的disabled属性
      •  debounce(func,wait){
          let timer=0
          return function(...args)=>{
              if(timer) clearTimeout(timer)
              timer=setTimeout(()=>{
                  func.apply(this,args)
              },wait)
            }
          }
        
    • 节流 每隔一段时间执行
    •  throttle(fn,wait,time){
           var timer=null;
           var previous=null;
           return function(){
               var now=+new Date()
               if(!previous) previous=now;
               if(now-previous>time){
                   clearTimeout(timer)
                   fn()
                   previous=now
               }
               clearTimeout(timer)
               timer=setTimeout(()=>{
                   fn()
               },wait)
      
           }
       }
      
  10. setTimeout
    • 倒计时
    function dida(wait){
        wait--;
        console.log(wait)
        t=setTimeout(()=>{
            dida(wait)
        },1000)
        if(wait==0) clearTimeout(t)
    }
    
    • 模拟实现call
    Function.prototype.mycall=function(context){
        var contenxt=context||window
        context.fn=this
        var args=[...arguments].slice(1)
        context.fn(...args)
        delete context.fn
    }
    
    • 模拟实现apply
    Function.prototype.myapply=function(context){
        var contenxt=context||window
        context.fn=this
        context.fn(...arguments[1])
        delete context.fn
    }
    
    • 模拟bind
    Function.prototype.mybind=function(context){
        var me=this
        var args=[...arguments].slice(1)
        return function F(){
            if(this instanceof F) {
                return new me(...args,...arguments)
            }
            return me.apply(context,args.concat(...arguments))
        }
    }
    
  11. promise,then/catch/try,all,race,resolve,reject
  12. 0.1 + 0.2 != 0.3原因: JS 采用 IEEE 754 双精度版本(64位),0.1的二进制是个二进制无限循环小数,parseFloat((0.1+0.2).toFixed(10))
  13. 数组去重
    • es6新数据结构Set,值唯一,set.add(item),[...new Set(arr)]/Array.from(new Set(arr))去重的数组
    • forEach()/for循环,indexof判断索引
    • 对象属性值唯一
  14. 垃圾回收GC算法,将内存(堆)
    • 新生代:存活时间端的对象,新分配的对象存from,满了后,将存活的对象复制到to,from清空,互换
    • 老生代:存活时间长,数量多的对象,标记清除算法和标记压缩算法,to空间超过25%就移到老生代空间

  1. 事件触发:w3c先捕获,到了目标元素再冒泡,冒泡(默认false),ie只支持冒泡,另外给一个元素同时都加了冒泡和捕获,先冒泡在捕获
    • window.event.cancelBubble = true关闭捕获冒泡
    • event.stopPropagation()阻止事件冒泡
    • event.preventDefat()阻止默认行为(超链接跳转)
  2. 事件代理/委托:把注册事件加在父节点上,节省内存
  3. 跨域:
    • jsonp动态添加script,用get请求,jquery dataType:jsonp
    • cors跨域资源共享 服务器端设置access-control-allow-origin
    • nginx代理跨域
    • document.domain二级域名相同时可用
    • postmessage(data,origin),h5 api
    • websoket ,h5
    • 开发环境设置浏览器: disable-web-security 关闭安全策略
    • vue nodejs中间件设置代理服务器proxy changeorigin:true
  4. 事件循环:js在执行过程中产生执行环境,执行环境按顺序加入执行栈,异步的代码会被挂起加入到task队列,执行栈为空会从task任务队列中拿出需要执行的代码放到队列中
    • settimeout有4ms的延时
    • 主线程=>process.nexttick=>promise=>Object.observe(微任务)=>settimeout(宏任务)
  5. cookie属性value,http-only(不能通过js获取,减少xss),secure(https才能携带),same-site(跨域不能带,减少csrf)
  6. serviceWorker缓存文件
  7. 浏览器渲染:
    • 处理html构建dom树
    • cssom树
    • 合并成一个渲染树
    • 布局计算节点位置
    • 绘制
  8. load事件是等dom,css,js,图片加载完毕,domcontentloaded是html被加载解析
  9. 重绘改变外观不影响布局,回流是布局改变
  10. jquery对象转dom对象 $("#a").get(0),反之,$(dom对象)

  1. 性能
    • dns预解析
    • 缓存
      • 强制缓存cache-control,expires,返回200
      • 协商缓存last-modified/if-modified-since,etag/if-none-match,返回304
    • http2.0多路复用,header压缩
    • 预加载 link rel="preload"
    • 预渲染 link rel="prerender"
    • 懒执行,懒加载(图片)
    • 图片优化
      • 压缩图片
      • 雪碧图
      • 小图用base64
      • 懒加载
        • src里用一个占位图
        • window.onscroll+节流/防抖函数
        • 根据document.body.scrolltop||document.documentElement.scrolltop
        • 给所有的图片加class,函数里面for循环遍历img,判断图片的offsettop是否小于scrolltop,小于则替换src,该class删除
    • css放head
    • script放body底
    • cdn加载静态资源
    • webpack打包压缩,按路由拆分代码,按需加载const F=()=>import("")
    • window.onerror报错
  2. xss,跨站脚本攻击,评论里一个带恶意script,转义,内容安全策略 (CSP),设置 Header 中的 Content-Security-Policy
  3. csrf,验证referer

  1. mvvm:model和view独立,由viewmodel作为桥梁只关心数据和业务的处理,不关心view如何处理数据
    • vue数据劫持:vue遍历data中所有的属性,Object.defineProperty(obj,key,{})实现数据绑定,监听数据的set和get事件,给添加发布订阅,get中添加订阅,set中发布,手动触发一次属性的 getter 来实现发布订阅的添加
  2. 路由:监听url的变化,匹配路由规则,显示页面,无须刷新,由hash模式和history模式
  3. virtual dom:操作dom费时,用js对象模拟dom对象,操作js对象比操作dom省时, diff算法之比对同层节点,O(n)复杂度,局部更新dom
    • tags字符串,document.createElement(tag)
    • props对象,el.setAttribute(key, props[key])
    • children数组,
    • key唯一表示标识,el.setAttribute('key', key)

  1. nextTick是在下次 DOM 更新循环结束之后执行延迟回调

  2. vue生命周期:new vue实例,beforecreate:data,props还没有

  3. 组件

    • 组件的data必须是函数,每个实例都可以维护return的对象的独立的拷贝,不会影响其他实例
    • 组件注册:Vue.component全局注册(在根 Vue 实例创建之前发生),局部注册components:{ComponentA}
    • 每个组件只有一个根元素
    • emit方法传入事件名,向父组件触发监听的事件,以修改子组件的prop
    • v-model是v-bind:value=“x” v-on:input=“x=$event.target.value”,默认名为value 的prop和input事件
    • 原生事件v-on:事件名.native修饰符
    • 动态组件加keep-live缓存
  4. 计算属性computed:{xx:{get:function(){},set:function(){}},基于它们的依赖进行缓存的, 侦听属性watch:{xx:function(){}}

  5. 冒泡排序

    function maopao(arr){
        var item;
        for(var i=0;i<arr.length;i++ ){
            for(var j=i;j<arr.length;j++){
                if(arr[j]>arr[j+1]){
                    item=arr[j]
                    arr[j]=arr[j+1]
                    arr[j+1]=item
                }
            }
        }
    }
    
  6. 全排列

    function swap(array,i,j){
        var t;
        t = array[i];
        array[i] = array[j]; 
        array[j] = t;
    }
    function permutation(ls) {
        return ls.length ? ls.reduce((acc, x) => acc.concat(permutation(ls.filter(e => e != x)).map(a => [x].concat(a))), []) : [[]];
    }
    console.log(permutation([1, 2, 3]));
    
  7. json转树形结构

    var nodes = [
        {"id":2,"cname":"第一级1","ipid":0},
        {"id":3,"cname":"第一级1","ipid":2},
        {"id":4,"cname":"第一级1","ipid":2},
        {"id":5,"cname":"第一级1","ipid":4},
        {"id":6,"cname":"第一级1","ipid":3},
        {"id":7,"cname":"第一级1","ipid":0}
    ]		
    function transDate(list,idstr,pidstr){
        var result = [],temp = {};
        for(i = 0; i < list.length; i++){
            temp[list[i][idstr]]=list[i];//将nodes数组转成对象类型
        }
        for(j=0; j<list.length; j++){
            tempVp = temp[list[j][pidstr]]; //获取每一个子对象的父对象
            if(tempVp){//判断父对象是否存在,如果不存在直接将对象放到第一层
                if(!tempVp["nodes"]) tempVp["nodes"] = [];//如果父元素的nodes对象不存在,则创建数组
                tempVp["nodes"].push(list[j]);//将本对象压入父对象的nodes数组
            }else{
                result.push(list[j]);//将不存在父对象的对象直接放入一级目录
            }
        }
        return result;
    }
    console.log(transDate(nodes,"id","ipid")); 
    
  8. ajax,axios,fetch

    • ajax异步 async:true默认,对原生XHR的封装,还增添了对JSONP的支持
      ajax({
          method: 'GET',
          url: '/',
          success: function(responseText){}
      })
      function ajax(options){
          let xhr = new XMLHttpRequest()
          xhr.open(method, url)
          xhr.onreadystatechange = function(){
              if(xhr.readyState === 4){
              if(xhr.status>=200 && xhr.status < 400){
                  success && success.call(null, xhr.responseText, xhr)
              }else if(xhr.status >= 400){
                  error && error.call(null, xhr.status, xhr)
              }
              }
          }
          xhr.send()
      }
      
    • promise实现Axios本质上也是对原生XHR的封装,提供了一些并发请求的接口,客户端支持防止CSRF
      axios({method: 'GET', url: '/x'}).then(SuccessFn1, commonErrorFn)
      function ajax(options){
          return new Promise(function(resolve, reject){ 
              let xhr = new XMLHttpRequest()
              xhr.open(method, url)
              xhr.onreadystatechange = function(){
                  if(xhr.readyState === 4){
                      if(xhr.status>=200 && xhr.status < 400){
                          resolve(xhr.responseText) 
                      }else if(xhr.status >= 400){
                          reject(xhr) 
                      }
                  }
              }
              xhr.send()
          })
      }
      
    • fetch
    try {
        let response = await fetch(url);
        let data = response.json();
        console.log(data);
    } catch(e) {
    console.log("Oops, error", e);
    }
    
  9. hash和history

    • hash原理window.onhashchange事件
    • history原理history api (pushState、replaceState、go、back、forward),在window对象上监听popState()事件
      history.go(-2);//后退两次
      history.go(2);//前进两次
      history.back(); //后退
      hsitory.forward(); //前进
      
  10. computed和watch

    • computed根据一个变量计算得到另一个属性,计算属性具有缓存,多次访问不必重新执行那个函数,一个数据依赖于其他数据时使用
    • watch是监听一个值的变化,执行对应函数,在数据变化是做些事情
  11. 异步编程

    • 回调函数(f2写成f1的回调函数)不利于阅读维护,每个任务只能制定一个回调函数
          function f1(callback){
              setTimeout(function(){
                  //f1的代码
                  callback();
              },1000);
          }
      
    • 事件监听 事件驱动模式,取决于某个事件是否发生
       function f1(){
           setTimeout(function(){
               //f1的代码
               f1.trigger('done');
           },1000);
       }
       f1.on('done',f2)
      
    • 发布/订阅
      jQuery.subscribe("done",f2)
      function f1(){
          setTimeout(function(){
              //f1的代码
              jQuery.publish('done');
          },1000);
      }
      jQuery.unsubscribe("done", f2);
      
    • promise对象,为异步编程提供统一接口,回调函数变成链式写法,流程很清楚
        f1().then(f2)//then(成功回调函数,失败毁掉函数)
        f1().then(f2).then(f3);//链式写法是在回调函数执行完后return返回结果作为下一个then的回调函数的参数
        f1().then(f2).fail(f3);