32
  1. <script>
    defer 脚本延迟执行,适用于外部脚本文件
    async 立即下载,不保证顺序(建议不修改DOM,避免重绘)
    CDN加速 (Content Delivery Network,内容分发网络) 提高访问网站的响应速度

    <script>
     function loadScript(){
        document.write(unescape("%3Cscript src='防错文件' %3E%3C/script%3E"))
      }
    </script>
    <script src="cdn文件" onerror="loadScript()"></script>
  2. 内存
    js内存回收机制:解除引用
    内存溢出:内存不够,系统会提示内存溢出,有时候会自动关闭软件
    内存泄漏:未能释放已经不再使用的内存,不是指内存在物理上的消失,而是内存的浪费
    常见内存泄漏情形:1.全局变量、2.被忘记的Timers或者callbacks、3.闭包、4.DOM引用
  3. 闭包
    概念:有权访问另一个函数作用域的变量的函数
    作用:匿名自执行函数、结果缓存、封装、实现类和继承
  4. 函数封装模式

    //工厂模式:在函数中返回一个创建并返回一个对象
    function createClass0(params){
      var o = new Object();
      o.name = params;
      o.fn0 = function(){
        console.log(this.name);
      }
      return o;
    }
    
    var obj = createClass0(params);
    console.log(obj.constructor == createClass0); //false
    console.log(obj instanceof createClass0); //false
    
    //构造函数模式:es6的类也是通过该模式实现
    function Class0(params){
      this.name = params;
      this.fn0 = fn0;
      this.fn1 = function(){
        console.log(this.name)
      }
    }
    function fn0(){
      console.log(this.name)
    }
    
    var obj = new Class0(params);
    console.log(obj.constructor == Class0); //true
    console.log(obj instanceof Class0); //true
    
    //原型模式:属性与方法挂在原型链上
    function Class0(){}
    Class0.prototype = {
      name: params,
      fn0: function(){
        console.log(this.name)
      }
    }
    var obj = new Class0();
    console.log(obj.constructor == Class0);//true
    console.log(obj instanceof Class0); //true
    Object.defineProperty(Class0.prototype,"constructor",{
      enumerable: false,
      value: Class0
    })
    console.log(obj.constructor == Class0); //false
    
    //动态原型模式:
    function Class0(params){
      this.name = params;
      if(typeof this.fn0 != "function"){
        Class0.prototype.fn0 = function(){
          console.log(this.name)
        }
      }
    }
    var obj = new Class0(params);
    console.log(obj.constructor == Class0); //true
    console.log(obj instanceof Class0); //true
    
    //寄生构造函数模式:
    function Class0(params){
      var o = new Object();
      o.name = params;
      return o;
    }
    
    var obj = new Class0(params);
    console.log(obj.constructor == Class0); //false
    console.log(obj instanceof Class0); //false
    
    //稳妥构造函数模式:无法访问其属性
    function Class0(params){
      var o = new Object();
      var name = params;
      o.fn0 = function(){
        console.log(name);
      }
      return o;
    }
    
    var obj = Class0(params);
    console.log(obj.constructor == Class0); //false
    console.log(obj instanceof Class0); //false
    
    //继承:js没有借口继承,只有实现继承,依靠原型链实现
    //经典继承:借用构造函数
    function Class0(params){
      this.name0 = params;
      this.fn0 = function(){
        console.log(this.name);
      }
    }
    function subClass0(params){
      Class0.call(this,params);  
      this.name1 = params;
      subClass0.prototype.fn1 = function(){
        console.log(this.name1);
      }
    }
      
    var obj = new subClass0(params);
    console.log(obj.constructor == subClass0); //true
    console.log(obj instanceof subClass0); //true
    console.log(obj.constructor == Class0); //false
    console.log(obj instanceof Class0); //false
    
    //组合继承:es6类的继承通过该模式实现
    function Class0(params){
      this.name0 = params;
      this.fn0 = function(){
        console.log(this.name0);
      }
    }
    function subClass0(params){
      Class0.call(this,params);
      this.name1 = params;
      subClass0.prototype.fn1 = function(){
        console.log(this.name1);
      }
    }
    subClass0.prototype = new Class0();
    subClass0.prototype.constructor = subClass0;
    
      
    var obj = new subClass0(params);
    console.log(obj.constructor == subClass0); //true
    console.log(obj instanceof subClass0); //true
    console.log(obj.constructor == Class0); //false
    console.log(obj instanceof Class0); //true
  5. BOM
    概念:浏览器对象模型
    核心对象:window,通过js访问浏览器窗口的一个接口,也是ECMAScript规定的Global对象。
    窗口框架:frameiframe
    窗口位置:window.screenLeft/window.screenX,window.moveBy(x,y); window.moveTo(x,y);
    窗口大小:window.resizeTo(width,height); window.resizeBy(dWidth,dHeight);
    导航弹窗:let win = window.open("..."); win.close();
  6. location
    hashURLhash字符串
    host:服务器名称和端口号
    hostname:服务器名称
    href:当前加载页面的完整URL
    pathnameURL中的目录
    portURL中制定的端口号
    prptocol:页面使用的协议
    searchURL的查询字符串,以?开头
    改变URL会生成新记录,禁用历史记录跳转可通过location.replace("...")实现
    刷新页面:location.reload(); location.reload(true);
  7. navigator

    离线检测:onLine
    地理信息:geolocation
    navigator.geolocation.getCurrentPosition((position)=>{
      //成功的回调
    },(error)=>{
      //错误的回调
    },{
      enableHighAccuracy: true, //尽可能使用最准确的位置信息
      timeout: 5000,  //等待位置信息的最长时间
      maximumAge: 25000 //上一次取得坐标信息的有效时间,时间到则重新获取
    });
    
    //跟踪监控
    let watchId = navigator.geolocation.watchPosition(position)=>{
      //成功的回调
    },(error)=>{
      //错误的回调
    });
    
    clearWatch(watchId); //关闭跟踪
    
    浏览器中安装的插件信息:plugins
    //IE浏览器无效
    function hasPlugin(name){
      return Array.from(navigator.plugins).some(item => item.name.toLowerCase().includes(name.toLowerCase()) )
    }
    hasPlugin("Flash");
    //IE浏览器
    function hasIEPlugin(name){
      try{
        new ActiveXObject(name);
        return true;
      }catch(ex){
        return false;
      }
    }
    hasIEPlugin("ShockwaveFlash.ShockwaveFlash");
    
    cookie是否启用:cookieEnabled
    浏览器所在的系统平台:platform
    用户代理:userAgent(可用于判断浏览器引擎、版本、终端等)
    
    //简易的浏览器类型判断
    function browserType(){ //判断浏览器类型
      let userAgent = navigator.userAgent;
      let type;
      switch(userAgent){
        case userAgent.includes("MSIE"):
          type = "IE";
          break;
        case userAgent.includes("Firefox"):
          type = "Firefox";
          break;
        case userAgent.includes("Chrome"):
          type = "Chrome";
          break;
        case userAgent.includes("Opera"):
          type = "Opera";
          break;
        case userAgent.includes("Safari"):
          type = "Safari";
          break;
        case userAgent.includes("Netscape"):
          type = "Netscape";
          break;
        default:
          console.log(userAgent);
          break;
      }
      return type;
    }
  8. history
    页面前进:history.forward(); history.go(1);
    页面后退:history.back(); history.go(-1);
    跳转至可能存在的最近某个页面(不存在则什么都不做):history.go("...");
    历史记录数量:history.length(hash改变会使历史记录增加)
  9. 系统对话框

    alert(val); //警告窗
    confirm(val); //确认窗,选择OK,则返回true
    prompt(val,""); //输入窗,选择OK,则返回输入框内容,否则返回null
  10. 数据存储
    cookie:信息越大,对服务器的请求时间越长,故浏览器对其大小有限制,总量不到4K

    //创建cookie
    function setCookie(name, value, expires, path, domain, secure) {
      var cookieText = encodeURIComponent(name) + '=' + encodeURIComponent(value);//防止中文乱码,所以需要编码
      (expires instanceof Date) && (cookieText += '; expires=' + expires); //有效期
      path && (cookieText += '; path=' + path); //设置域的路径
      domain && (cookieText += '; domain=' + domain); //设置哪个域的请求中都会包含该cookie信息,默认为设置cookie的域
      secure && (cookieText += '; secure'); //只有在使用SSL连接的时候才发送到服务器
      document.cookie = cookieText;
    }
    
    //获取cookie
    function getCookie(name) {
      var cookieName = encodeURIComponent(name) + '=';
      var cookieStart = document.cookie.indexOf(cookieName);
      var cookieValue = null;
      if (cookieStart > -1) {
        var cookieEnd = document.cookie.indexOf(';', cookieStart);
        if (cookieEnd == -1) {
          cookieEnd = document.cookie.length;
        }
        cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
      }
      return cookieValue;
    }
    
    //删除cookie
    function unsetCookie(name) {
      document.cookie = name + "= ; expires=" + new Date(0);
    }

    localStorage:本地存储,容量5M左右,值类型限定为string类型,localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡,另外在部分浏览器隐私模式下不可读取。
    sessionStorage:会话存储(刷新页面依旧存在),与localStorage在持久上不同外,其余一致。
    indexedDB:储存空间不少于250M,没有上限,异步设计,支持二进制储存(ArrayBuffer对象和Blob对象)
    localforagejs库,异步操作(自动加载最佳驱动程序,从IndexedDBlocalStorage

    //存储
    localforage.setItem('key', 'value');
    
    localforage.setItem('key', 'value').then(()=>{
      ...
    }).catch(err=>{
      console.log(err);
    });
    
    localforage.setItem('key', 'value').then(()=>{
      return localforage.getItem('key');
    }).then(val=>{
      console.log(val);
    }).catch(err=>{
      console.log(err);
    });
    
    //获取
    localforage.getItem('key').then(()=>{
      ...
    }).catch(err=>{
      console.log(err);
    });
    
    //删除
    localforage.removeItem('key');
    
    localforage.removeItem('key').then(()=>{
      ...
    }).catch(err=>{
      console.log(err);
    });
    
    //清空
    localforage.clear();
    
    localforage.clear().then(()=>{
      ...
    }).catch(err=>{
      console.log(err);
    })
    
    //遍历
    localforage.iterate((value, key)=>{
      console.log(key,value);
    }).then(()=>{
      ...
    }).catch(err=>{
      console.log(err);
    });
  11. DOM

    //querySelector选择器,返回匹配的一个元素
    let parentElement = document.querySelector(".container");
    //创建元素
    let element = document.createElement("button");
    //设置元素的属性
    element.setAttribute("onclick", `javascript:alert('click the span!');`);  
    //设置内容,innerText有兼容性问题,采用innerHTML较为方便
    element.innerHTML = "创建元素添加的元素"; 
    //设置内联样式
    element.style.color = "blue";
    //在容器中末尾加入元素
    parentElement.appendChild(element);
    
    //添加元素的另一种方式,该方式适合一次性创建多节点
    let elementHtml = `<button style="color:blue" onclick="javascript:alert('click the span!');">innerHTML方式添加的元素</button>`
    parentElement.innerHTML += elementHtml;
    
    //元素的克隆.cloneNode(true),父节点.parentNode,首个子节点.firstChild、下一个兄弟节点.nextElementSibling,加入到某个元素的前面refNode.parentNode.insertBefore(newNode,refNode)
    parentElement.insertBefore(parentElement.parentNode.cloneNode(true), parentElement.firstChild.nextElementSibling);//克隆一份parentElement的父节点,并将其放在parentElement的第一个子元素的下一个元素的前面
    
    let newElement = element.cloneNode(true);
    newElement.innerHTML = "newElement";
    
    //容器的最后一个子元素.lastChild,上一个兄弟节点.previousElementSibling,替换元素refNode.parentNode.insertBefore(newNode,refNode)
    parentElement.replaceChild(newElement, parentElement.lastChild.previousElementSibling);//替换parentElement最后一个子元素的上一个元素
    
    //querySelectorAll选择器返回NodeList
    let firstContainer = document.querySelectorAll(".container")[0];
    
    //删除元素node.parentNode.removeChild(node),元素子节点.children
    firstContainer.removeChild(firstContainer.children[0]);//删除firstContainer这个元素的第一个子元素
    
    //动态添加样式规则
    document.querySelector("head").innerHTML += `<style>.container{ height: 800px; background: red; }</style>`
    
    //移动滚动条至firstContainer这个元素可见,true或不传表示元素顶端对齐,false表示底端在可视区域中间
    firstContainer.scrollIntoView(true);
    
    //获取元素的真正样式 window.getComputedStyle(element)
    console.log(window.getComputedStyle(firstContainer)) //获取元素的真正样式
    console.log(firstContainer.style); //获取元素的内联样式
    
    //获取元素的尺寸及相对于浏览器可视窗口的位置(非文档,故页面发生滚动会改变).getBoundingClientRect(),在计算坐标使用时可用clientX配合getBoundingClientRect().left
    console.log(firstContainer.getBoundingClientRect());
  12. 事件流
    事件流过程:捕获过程、目标、冒泡过程
    事件捕获:从大到小,极少使用
    事件冒泡:从小到大,常用,虽然各浏览器有些差异
    阻止冒泡:e.stopPropagation(),IE9前使用e.cancelBubble=true
    阻止默认行为:e.preventDefault(),IE9前使用e.returnValue=false
    默认行为:如表单按钮的提交,<a>标签的跳转等
    事件委托:利用事件冒泡,监听顶级的DOM(事件处理程序数量关系到页面的整体运行性能)
  13. 页面事件
    pageshow事件:页面显示时触发,事件目标为document,但必须将其事件处理程序添加到window,参数为event
    pagehide事件:页面卸载时触发,事件目标为document,但必须将其事件处理程序添加到window,参数为event
    haschange事件:URL的参数列表发生变化时触发,但必须将其事件处理程序添加到window,参数为event
    visibilitychange事件:绑定在document上,当页面最小化或切换浏览器标签等可见状态改变触发,documen.hidden可查看页面可见度状态

    document.addEventListener('visibilitychange',function(){
      console.log(document.hidden);
    })
  14. 表单事件
    默认行为:表单中的最后一个按钮会自动提交表单
    form.submit()主动提交表单
    form.reset()重置表单
    form.checkValidity()表单验证配合require和pattern使用
    noValidate属性禁用表单验证
    过滤输入,屏蔽某些词的默认行为:监听keypress事件,e.preventDefault();
    富文本编辑的实现:
    iframe实现,空文档的designMode设置为ongetSeclection事件获取具体信息;
    ②设置contenteditable属性实现,通过document.execCommand()实现富文本操作,如document.execCommand("blod", false, null);实现粗体文本。
  15. 鼠标事件
    双击事件顺序:mousedownmouseupclickmousedownmouseupclickdblclick
    移入容器事件顺序过程:mouseover(在不同元素间触发)、mouseentermousemovemouseout(在不同元素间触发)、mouseleave
    右键点击事件:contextmenu(H5事件)
    位置信息:
      clientX(鼠标相对于浏览器窗口可视区域的X坐标)
      offsetX(鼠标相对于事件源元素的X坐标,存在兼容性问题)
      screenX(鼠标相对于用户显示器屏幕左上角的X坐标)
      pageX(鼠标相对于文档区域的X坐标,存在兼容性问题)
    event对象属性:
      type(事件类型)
      detail(点击次数)
      target(事件源元素)
      path(数组,冒泡的路径)
  16. 拖放事件
    相关事件:dragstart、drag、dragend、dragenter、dragover、dragleave、drop

    <section ondrop="drop(event)" ondragover="dragover(event)">投放目标</section>
    <div id="dragObj" src="xxx" draggable="true" ondragstart="drag(event)">被拖拽的物体</div>
    
    dragover(e){
      e.preventDefault();
    }
    drag(e){
      e.dataTransfer.setData("id",e.target.id);
    }
    drop(e){
      e.preventDefault();
      let data = e.dataTransfer.getData("id");
      e.target.appendChild(document.getElementById(data));
    }
  17. 触摸与手势事件
    移动端点击事件顺序:touchstarttouchendmouseovermouseentermousemovemousedownmouseupclick
    touchmove事件:需要阻止默认行为以防止屏幕滚动
    touchcancel事件:当系统停止跟踪触摸时触发
    gesturestart事件:当一个手指已经按在屏幕上而另一个手指又触摸时触发
    gesturechange事件:当触摸屏幕的任何一个手指的位置发生变化时改变
    gestureend事件:当任何一个手指从屏幕上面移开时触发
    触摸事件特有的event对象属性:
      touches(表示当前跟踪的触摸操作的Touch对象的数组)
      targetTouchs(特定于事件目标的Touch对象的数组)
      changeTouches(上次触摸以来发生了什么改变的Touch对象的数组)
      rotation(手势变化引起的旋转角度,从0开始,顺正逆负)
      scal(手指间的距离变化,从1开始,与距离呈正相关)
  18. 模拟事件
    UIEvents UI事件
    MouseEvents 鼠标事件
    MutationEvents DOM变动事件
    HTMLEvents HTML事件

    模拟鼠标点击事件:
    1.创建鼠标事件的event对象
    let event = document.createEvent("MouseEvents");
    2.设置触发的参数 //可简写,如event.initMouseEvent('click');
    event.initMouseEvent(事件类型,...event对象其他参数);
    /*参数顺序:type、bubbles(是否冒泡)、cancelable(事件是否可取消)、view(document.defaultView)、detail、screenX、screenY、clientX、clientY、ctrlKey(是否按下ctrl)、altKey(是否按下alt)、shiftKey(是否按下shiftKey)、metaKey(是否按下metaKey)、button(表示按下哪个鼠标键)、relatedTarget(事件相关的对象,用于模拟mouseover/mouseout)*/
    3.触发事件
    document.getElementById('btn').dispatchEvent(event);
  19. 媒体元素
    音频播放器:audio
    视频播放器:video
    通过play()pause()可手工控制媒体文件的播放和暂停,ended事件当播放结束时触发
  20. 绘图技术
    canvas:2D绘图,可进行图片与图像的互转,通过变换和合成绘制复杂图像

    //获取canvas内容生成的URI
    let imgURI = canvas.toDataURL("image/png");
    let img = document.createElement("img");
    img.src = imgURI;
    document.body.appendChild(img);

    svg:支持事件驱动,通过foreignObject可实现svg和普通HTML元素的融合
    WebGL:3D绘图,非W3C标准

  21. ajax
    Asynchronous Javascript And XML,即异步JavaScript和XML,是一种创建交互式网页应用的网页开发技术。

    //封装ajax
    function ajax(obj) {
      var xhr = new XMLHttpRequest(); //创建XMLHttpRequest实例
      obj.url = obj.url + '?rand=' + Math.random(); //为url加时间戳
      if(obj.method === 'get') obj.url += '&' + obj.data;
      if(obj.async) xhr.onreadystatechange = ()=>{ (xhr.readyState == 4) && callback(); } //异步请求当readyState == 4才执行回调
      xhr.open(obj.method, obj.url, obj.async); //发送请求
      if(obj.method === 'post'){
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send(obj.data); 
      }else{
        xhr.send(null);
      }
      if(!obj.async) callback(); //同步请求
      function callback() {
        if(xhr.status == 200){ obj.success(xhr.responseText); } //回调传递参数
        else{ console.log('获取数据错误!错误代号:' + xhr.status + ',错误信息:' + xhr.statusText); }
      }
    }
    
    ajax({
      method : 'post/get',
      url : '...',
      data : "",
      success : (res)=>{
        console.log(res);
      },
      async : true
    });
  22. get与post请求
    get请求:从指定的资源请求数据,数据量和类型有限制(因为数据放在请求头中,浏览器对其长度有限制),会被缓存,且数据在url上可见,导致安全性相对低点。
    post请求:向指定的资源提交被处理的数据,数据量和类型没限制,不主动缓存,页面刷新数据会被重新提交。
    底层分析:对于get请求,浏览器会把http headerdata一并发送出去,服务器响应200(返回数据),整个过程产生一个TCP数据包;对于post请求,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据),整个过程产生两个TCP数据包,导致时间消耗,网络环境畅通情况下可无视。
  23. File API

    let reader = new FileReader();
    reader.readAsText(file,encoding); //以纯文本的形式读取文件,读取到的文本保存在result属性中
    //reader.readAsDataURL(file); //读取文件以数据URI的形式保存在result属性中
    //reader.readAsBinaryString(file); //读取文件并将一个字符串保存在result属性中,字符串中的每个字符表示一字节
    //reader.readAsArrayBuffer(file); //读取文件并将一个包含文件内容的ArrayBuffer保存在result属性中
    reader.progress = (event)=>{
      if(event.lengthComputable){
        console.log(event.loaded + '/' + event.total);
      }
    }
    reader.onerror = ()=>{
      console.log(reader.error.code);
    }
    reader.onload = function(){
      console.log(reader.result);
    }
  24. 对象防篡改

    Object.preventExtensions(obj);  //对象不可拓展,禁止添加属性或方法
    Object.seal(obj); //密封对象,不可删除属性和方法
    Object.freeze(obj); //冻结对象,不可拓展、且密封、不可编辑
  25. String、JSON、Object相互转化

    //js对象转JSON
    function jsToJSON(obj){
      let objFnToStr = fnToStr(obj);
      return JSON.stringify(objFnToStr);
    }
    
    //字符串转JSON
    function strToJSON(str){
      let obj = eval('('+str+')');
      return jsToJSON(obj);
    }
    
    //JSON转js对象
    function JSONToJs(json){
      let obj = JSON.parse(json);
      return strToFn(obj);
    }
    
    //将js对象中的函数字符串解析为函数
    function strToFn(obj){
      var o = obj instanceof Array ? [] : {};
      for(var k in obj) {
        switch(typeof(obj[k])){
          case 'object':
            o[k] = obj[k] ? strToFn(obj[k]) : null;
            break;
          case 'string':
            o[k] = obj[k].match(/^\s*(function\s*\(.*\)\s*)|(\(.*\)\s*\=>\s*)/) ? eval('('+obj[k]+')') : obj[k];
            break;
          default:
            o[k] = obj[k];
            break;
        }
      }
      return o;
    }
    
    //将js对象中的函数类型转为字符串
    function fnToStr(obj){
      var o = obj instanceof Array ? [] : {};
      for(var k in obj) {
        switch(typeof(obj[k])){
          case 'object':
            o[k] = obj[k] ? fnToStr(obj[k]) : null;
            break;
          case 'function':
            o[k] = obj[k] + '';
            break;
          default:
            o[k] = obj[k];
            break;
        }
      }
      return o;
    }
  26. 定时器

    //延迟调用
    let timeId = setTimeout(fn,time);
    clearTimeout(timeId);
    
    //间歇调用
    let timeId = setInterval(fn,time);
    clearInterval(timeId);
    
    //定时器中的定时器
    setTimeout(function(){
      //...
      setTimeout(arguments.callee, interval);
    })
    
    //沉睡排序法
    [1,5,2,4,100,3].forEach(n=>{
      setTimeout(()=>{ console.log(n) }, n);
    })
  27. html与文本的转换

    //字符串转html字符串,参数:html传入的字符串,type是否返回标签结构,默认只返回内容,escape表示是否需要转义
    function escapeHtml(html,type,escape){ //type:content/html,escape:转义/不转义
      let objE = document.createElement("div");
      objE.innerHTML = html;
      type 
        ? (escape 
          ? (html.includes('&') ? (objE.innerText = html) : (objE.innerText = new Option(html).innerHTML)) 
          : (html.includes('<') && (objE.innerText = html)))
        : (objE.innerHTML = objE.innerText);
      return objE.innerText;
    }
  28. 错误处理

    //监听除 try catch 捕捉的错误
    window.onerror = (...error)=>{
      window.open("http://stackoverflow.com/search?q=[js] + "+error[0]);
    }
    
    //强制报错
    var err = new Error("错误信息");
    console.error(err); //单纯日志输出,不影响代码执行
    throw err; //显示报错,导致后面代码不解析

星空
1.3k 声望15 粉丝

« 上一篇
Vue入坑笔记