JavasSript

ES6 Promise 对象

从语法上说, Promise 是一个对象, 从它可以获取异步操作的消息; Promise 异步操作有三种状态: pending(进行中), fulfilled(已成功)和 rejected(已失败);除了异步操作的结果, 任何其他操作都无法改变这个状态;

Promise 对象只有: 从 pending 变为 fulfilled 和从 pending 变为 rejected 的状态改变;只要处于 fulfilled 和 rejected , 状态就不会再变了即 resolved(已定型);

const promise = new Promise(function(resolve,reject){
    //修改为成功状态, then 回调
     resolve('success1');
     //修改为失败状态,catch 回调
    //reject('reject');
})
promise.then(function(res){  
    resolve(res); 
}).catch(function(err){
    reject(err);
});
 
  
let p3 = p2.then(function(value){ 
    console.log(value); // success3
    return "p2 ok"//这里的返回值, p3的 then 可以接受到
}).catch(function(err){
    console.log(err);
    return "p2 fail"//这里的返回值, p3的 then 可以接受到
});
p3 .then(res=>{
    console.log(res);// "p2 ok" 或者 "p2 fail"
})
.catch(res=>{
    //这里永不会调用
}
 
///调用所有的 Promise
Promise.all([p1, p2]).then(result => {
  call(true);
}).catch(errs=>{
  call(false);
})
 

ES6 async 函数

async 函数中可能会有await,async 函数执行时,如果遇到 await 就会先暂停执行 , 等到触发的异步操作完成后, 恢复 async 函数的执行并返回解析值;

await 关键字仅在 async function 中有效; 如果在 async function 函数体外使用 await , 你只会得到一个语法错误; await 操作符用于等待一个 Promise 对象, 它只能在异步函数(async function) 内部使用;

function testAwait(){
   return new Promise((resolve) => {
       setTimeout(function(){
          console.log("testAwait");
          resolve();
       }, 1000);
   });
}
 
async function helloAsync(){
   await testAwait();
   console.log("helloAsync");//1 /会等待testAwait()的Promise 执行完毕
   
 }
helloAsync();//2 /不会等待 
console.log("testAwait2");
//输出↓
// testAwait2
// testAwait
// helloAsync

注意一点, 效果是: 在代码1处, 会等待testAwait()函数执行完毕获取到返回值, 但在代码2处(async外面),还是异步的不会等testAwait()的返回, 继续向下执行!!

菜鸟教程 - ES6 async 函数

ES6 队列实现一则

let Queue = (function(){
    const items = new WeakMap()
    
    class Queue {
        constructor(){
            items.set(this,[])
        }
        enqueue(element){
            let q = items.get(this)
            q.push(element)
        }
        dequeue(){
            let q = items.get(this)
            let r = q.shift()
            return r
        }
        size(){
            let q = items.get(this)
           return q.length
        }
        print(){
            let q = items.get(this)
            console.log(q.toString())
        }
    }
    
    return Queue
})()
export default Queue
 
//使用
import Queue from './Queue'
var a = new Queue();
a.enqueue(123)
 

(https://www.cnblogs.com/pluslius/p/10331661.html)

call(), apply(), bind()

call(), apply(), bind() 都是可以用来重定义 this

第一个参数都是 this 的指向对象, call 的参数是直接放进去的, 第2 3 N个参数全都用逗号分隔, 直接放到后面 obj.myFun.call(this,‘参数2’, ‘参数3’ ); apply 的所有参数都必须放在一个数组里面传进去 obj.myFun.apply(this,[‘参数2’, ‘参数3’ ]);

bind 除了返回是函数以外, 它的参数和 call 一样;

JavaScript 标准

MDN JavaScript

最大安全整数值

MAX_SAFE_INTEGER 是一个值为 9007199254740991 的常量; 因为Javascript的数字存储使用了IEEE 754中规定的双精度浮点数数据类型, 而这一数据类型能够安全存储 -(2^53 - 1) 到 2^53 - 1 之间的数值(包含边界值);

MDN

JS 的最大和最小安全值可以这样获得:

console.log(Number.MAX_SAFE_INTEGER); //9007199254740991 = 2^53-1
console.log(Number.MIN_SAFE_INTEGER); //-9007199254740991

标准内置对象

MDN JavaScript 标准内置对象

集合处理

数组元素分组

const array = [
    { id: 1, typeId: 'A' },
    { id: 2, typeId: 'B' },
    { id: 3, typeId: 'A' },
    { id: 4, typeId: 'C' },
    { id: 5, typeId: 'B' },
    { id: 6, typeId: 'A' },
    { id: 7, typeId: 'C' },
];
 
const groupedById = array.reduce((acc, obj) => {
    const typeId = obj.typeId;
    if (!acc[typeId]) {
        acc[typeId] = [];
    }
    acc[typeId].push(obj);
    return acc;
}, {});
 
console.log(groupedById);
// out
{"A": [{"id": 1,
        "typeId": "A"
        },
        {"id": 3,
        "typeId": "A"
        },
        {"id": 6,
        "typeId": "A"
        }
    ],
"B": [
        ...
    ],
"C": [
        ...
    ]
}

数组元素 求最大值

const objects = [
    { id: 1, value: 10 },
    { id: 2, value: 25 },
    { id: 3, value: 15 },
    { id: 4, value: 30 }
];
 
const maxObject = objects.reduce((max, obj) => max.value > obj.value ? max : obj);
console.log(maxObject); // 输出: { id: 4, value: 30 }

一些业务功能代码

将JsonObject 转为 FormData

 
function getFormData(obj, rootName, ignoreList) {
  var formData = new FormData();
 
  function appendFormData(data, root) {
      if (!ignore(root)) {
          root = root || '';
          if (data instanceof File) {
              formData.append(root, data);
          } else if (Array.isArray(data)) {
              for (var i = 0; i < data.length; i++) {
                  appendFormData(data[i], root + '[' + i + ']');
              }
          } else if (typeof data === 'object' && data) {
              for (var key in data) {
                  if (data.hasOwnProperty(key)) {
                      if (root === '') {
                          appendFormData(data[key], key);
                      } else {
                          appendFormData(data[key], root + '.' + key);
                      }
                  }
              }
          } else {
              if (data !== null && typeof data !== 'undefined') {
                  formData.append(root, data);
              }
          }
      }
  }
 
  function ignore(root){
      return Array.isArray(ignoreList)
          && ignoreList.some(function(x) { return x === root; });
  }
 
  appendFormData(obj, rootName);
 
  return formData;
}

copy from 这位老哥

读取文件为base64

var inputObj = document.createElement("input");
inputObj.type = "file";
inputObj.accept = ".jpg, .png";
inputObj.click();
inputObj.addEventListener("change", event => {
let fileObj = inputObj.files[0];//读取选中文件的文件名
if (fileObj) {
    var reader = new FileReader();//这是核心,读取操作就是由它完成.
    reader.readAsDataURL(fileObj)//读取 以url
    reader.onload = function(e) {//当读取完成后回调这个函数,然后此时文件的内容存储到了result中,直接操作即可
        this[pop] = +e.target.result//包括前缀 data:image/jpeg;base64,ffx
    }
}
});

Blob

下载Blob

function dl(blob, fileName) {
  // const blob = new Blob([content]);
  const a = document.createElement("a");
  const url = window.URL.createObjectURL(blob);
  const filename = fileName;
  a.href = url;
  a.download = filename;
  a.click();
  window.URL.revokeObjectURL(url);
}
 
 
 

读取Blob

// 创建FileReader对象
var reader = new FileReader();
// 当读取完成时的回调函数
reader.onloadend = function() {
  // 读取完成后,reader.result包含Base64编码的字符串
  console.log(reader.result);
};
// 以DataURL格式读取Blob,并触发onloadend事件
reader.readAsDataURL(myBlob);

纯前端 创建zip

JSZip API参考手册 git project

// 下载的文件名
const filename = new Date().getTime() + '_s.zip';
var zip = new JSZip();
 
 
    //添加一个文件
    zip.file("file.txt", "content");
 
    //访问该文件
    zip.file("file.txt").name // "file.txt"
    zip.file("file.txt").async("string") // a promise of "content"
    zip.file("file.txt").dir // false
 
 
    // 添加一个文件夹
    zip.folder("sub").file("file.txt", "content");
 
    zip.file("sub/file.txt"); // the file
    zip.folder("sub").file("file.txt") // the file
 
 
// 生成zip文件并下载
zip.generateAsync({
    type: 'blob'
}).then(function(content) {
    // 创建隐藏的可下载链接
    var eleLink = document.createElement('a');
    eleLink.download = filename;
    eleLink.style.display = 'none';
    // 下载内容转变成blob地址  // 触发
    eleLink.href = URL.createObjectURL(content);
    document.body.appendChild(eleLink);
    eleLink.click();
    document.body.removeChild(eleLink);
});
 

原生Ajax

post请求

function getTestToken(callback){
  var baseURL = process.env.BASE_API;
  var login = baseURL+'/auth/directLogin2'
  //创建异步对象  
  var xhr = new XMLHttpRequest();
  xhr.open('post', login );
  //设置请求的类型及url
  //post请求一定要添加请求头才行不然会报错
  xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
  //发送请求
  xhr.send('username=testUser&password=123456');
  xhr.onreadystatechange = function () {
  // 这步为判断服务器是否正确响应
  if (xhr.readyState == 4 && xhr.status == 200) {
      var json = JSON.parse(xhr.responseText);
      callback(json)
    } 
  }
} 

原生form 上传

var inputObj = document.createElement("input");
inputObj.type = "file";
inputObj.accept = ".model";
inputObj.click();
inputObj.addEventListener("change", event => {
  let fileObj = inputObj.files[0];
  if (fileObj) {
    var formData = new FormData();
    formData.append("modelFile",fileObj);//文件
    // formData.append("name","abc");//可追加 form
    var xhr = new XMLHttpRequest();
    xhr.open('post', './up_std_ref_item_model?id='+data.id );//请求参数
  // xhr.setRequestHeader("Content-type","multipart/form-data");//不能设置 表单头
    //发送请求
    xhr.send(formData);
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4 && xhr.status == 200) {
        var json = JSON.parse(xhr.responseText);
      } 
    }
  }
});

封装

 
function Ajax(options) {
    options = options || {};
    options.type = (options.type || "GET").toUpperCase();
    options.async = options.async || true;
    options.contentType = options.contentType || 'application/json';
    var params = getParams(options.data);
    var xhr;
    if (window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    }else{
        xhr = new ActiveXObject('Microsoft.XMLHTTP')
    }
    xhr.onreadystatechange = function () {
    	 if (xhr.readyState > 3){
            var status = xhr.status;
            if (status >= 200 && status < 300 ){
                options.success && options.success(xhr.responseText,xhr.responseXML);
            }else{
                options.error && options.error(status);
            }
        }
    };
    if (options.type == 'GET'){
        xhr.open("GET",options.url + '?' + params ,options.async);
        xhr.setRequestHeader('Content-Type',options.contentType);
        xhr.send(null)
    }else if (options.type == 'POST'){
        xhr.open('POST',options.url,options.async);
        // xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
        xhr.setRequestHeader('Content-Type',options.contentType);
        xhr.send(params);
    }
	function getParams(data) {
		var arr = [];
		for (var param in data){
			arr.push(encodeURIComponent(param) + '=' +encodeURIComponent(data[param]));
		}
		return arr.join('&');
	}
}
////
		Ajax({url: queryUrl,
	      type:'post',
	      data:{ id:'username'},
	      dataType:'json',
	      contentType:"application/json",
	      success:function(data){
	          console.log(data);
	      }, 
	      error :function(e){
	          console.error(e);
			      alert("查询错误! 请稍后再试.")
	      }
	  })
	}
  

封装dom (事件委托)

 
var dialog = function(){
 
  var self = this;
  this.elementBind = function(element = this.element){
        //绑定顶层的元素 及点击事件
		element.addEventListener("click",function(_this,e){
			e.bindElement = this;
			var dom = e.target;
			var even = "action";
            var ev;
            //向上遍历 
			for( ;; ){
				ev = dom.getAttribute(even);//获得属性
				if( ev ){
					break;//退出
				}else{
					dom = dom.parentElement;
					if( !dom &&dom == this ){//最顶层 & 自己 退出
						break;
					}
				}
			}
			if( ev ){//如果该 action 属性存在 执行
				_this[ev] && _this[ev].call(_this,e);
			}
		}.bind(element,this))
	}
 
	this.clickOk = function(){
		
    }
}
 
DBconfigDialog = function (ele){
    this.element = ele;
    this.db_option;
    var self = this;
    this.setOption =function(db_option){
        this.db_option = db_option;
    },
    this.getOption = function(){
        return db_option;
    },
	this.elementBind = function(element = this.element){
		element.addEventListener("click",function(_this,e){
			e.bindElement = this;
			var dom = e.target;
			var even = "action-click";
            var ev;
			for( ;; ){
				ev = dom.getAttribute(even);
				if( ev ){
					break;
				}else{
					dom = dom.parentElement;
					if( !dom &&dom == this ){
						break;
					}
				}
			}
			if( ev ){
				_this[ev] && _this[ev].call(_this,e);
			}
		}.bind(element,this))
  },
  this.getFormParam = function(){
  var paramArr = {};
    self.element.find("input[name],select[name],textarea[name]").each(function(index,domEle){
      var name = $(domEle).attr("name");
      var value = $(domEle).val();
      paramArr[name] = value;
      });
        return paramArr;
    },
    this.applyFormParam = function(param){
        self.element.find("input[name],select[name],textarea[name]").each(function(index,domEle){
            var name = $(domEle).attr("name");
            if(param[name]){
                $(domEle).val(param[name]);
            }
        });
    },
}

获取URL中的参数

//TODO 中文是乱码问题

{key: val}//形式

function getQueryParams() { 
    var url = location.search; //获取url中"?"符后的字串
    var theRequest = new Object();
        if (url.indexOf("?") != -1) {
            var str = url.substr(1);
            var strs = str.split("&");
            for(var i = 0; i < strs.length; i ++) {
                theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]); }
        }
        return theRequest;
}
var g_cookie_obj = {
      //time 过期时间 毫秒
      set:function(key,val,time){//设置cookie方法
          var date=new Date(); //获取当前时间
          date.setTime(date.getTime()+time);
          document.cookie=key + "=" + val +";expires="+date.toGMTString();  //设置cookie
      },
      get:function(key){//获取cookie方法
          var getCookie = document.cookie.replace(/[ ]/g,"");  //获取cookie, 并且将获得的cookie格式化, 去掉空格字符
          var arrCookie = getCookie.split(";")  //将获得的cookie以"分号"为标识 将cookie保存到arrCookie的数组中
          var tips;  //声明变量tips
          for(var i=0;i<arrCookie.length;i++){   //使用for循环查找cookie中的tips变量
              var arr=arrCookie[i].split("=");   //将单条cookie用"等号"为标识, 将单条cookie保存为arr数组
              if(key==arr[0]){  //匹配变量名称, 其中arr[0]是指的cookie名称, 如果该条变量为tips则执行判断语句中的赋值操作
                  tips=arr[1];   //将cookie的值赋给变量tips
                  break;   //终止for循环遍历
              }
          }
          return tips;
      },
      delete:function(key){ //删除cookie方法
          var date = new Date(); //获取当前时间
          date.setTime(date.getTime()-1000); //将date设置为过去的时间
          document.cookie = key + "=v; expires =" +date.toGMTString();//设置cookie
      }
  }

Map 实现

 
 //map 实现
 function Map(){
    this.data = {};
    this.get = function(key){
        return this.data[key];
    }
    this.put = function(key, val){
        data[key]= val;
    },
    this.remove = function(key){
        delete data[key];
    },
    this.returnArrayForValue = function(){
        let arr = new Array();
        for (const key in this.data) {
            if (this.data.hasOwnProperty(key)) {
                arr.push(this.data[key]);
            }
        }
        return arr;
    }
}

base64

原生实现

var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
function encode64(input) {
    input = escape(input);
    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;
    do {
        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);
        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;
        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }
        output = output +
            keyStr.charAt(enc1) +
            keyStr.charAt(enc2) +
            keyStr.charAt(enc3) +
            keyStr.charAt(enc4);
        chr1 = chr2 = chr3 = "";
        enc1 = enc2 = enc3 = enc4 = "";
    } while (i < input.length);
    return output;
}
function decode64(input) {
    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;
    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =  
    var base64test = /[^A-Za-z0-9\+\/\=]/g;
    if (base64test.exec(input)) {
    alert("Expect errors in decoding.");
    }
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
    do {
        enc1 = keyStr.indexOf(input.charAt(i++));
        enc2 = keyStr.indexOf(input.charAt(i++));
        enc3 = keyStr.indexOf(input.charAt(i++));
        enc4 = keyStr.indexOf(input.charAt(i++));
        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;
        output = output + String.fromCharCode(chr1);
        if (enc3 != 64) {
            output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
            output = output + String.fromCharCode(chr3);
        }
        chr1 = chr2 = chr3 = "";
        enc1 = enc2 = enc3 = enc4 = "";
    } while (i < input.length);
    return unescape(output);
}
 

浏览器自带的

window.btoa('china is so nb') // 编码
"Y2hpbmEgaXMgc28gbmI="
window.atob("Y2hpbmEgaXMgc28gbmI=") // 解码
"china is so nb"

requirejs 简易使用

github

<script src="${ctx}/js/require.js"></script>
<script >
//规定加载路径
 require.config({
    baseUrl:"${ctx}"
    ,paths: {
        "UdsetTable":["js/model_udset_table_data"]
        ,"UdsetTree":["js/lwz/app/plugin/dataModel/model/udset_dialog"]
    }
})
//加载
require(["UdsetTable","UdsetTree"], function(null_is_golbal, UdsetTree){
    var UdsetTree = new UdsetTree();
});
 
//UdsetTree 定义部分
define([],function(){
	var dialog = function(){
        //容器
        this.$topContainer;
        this.$ztreeContainer;
    
        //点击回调
        this.folderClickCall;
        this.dsetClickCall;
        
        //ztree对象
        this.zTreeObj;
        
        
	}
	dialog.prototype = {
 
    }   
    return dialog;
})
</script>

美化JSON为Html显示

美化JSON Html显示

监视对象属性修改

vue 2 的原理

Object.defineProperty(data_conf,"inner_edit",{
   set: function(value){ 
      debugger;
      return  value;
   },
}) 

调用浏览器打印

  var img = dialogel.getElementsByTagName("img")[0]
  
  var iframe = document.createElement('IFRAME');
  var doc = null;
  iframe.setAttribute('style', 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;');
  document.body.appendChild(iframe);
  doc = iframe.contentWindow.document;
  doc.write('<div>' + img.outerHTML + '</div>');
  doc.close();
  iframe.contentWindow.focus();
  iframe.contentWindow.print();
  if(navigator.userAgent.indexOf("MSIE") > 0) {
      document.body.removeChild(iframe);
  }

文件夹树 -搜索实现

const reg_key_ = new RegExp("根2文件", 'i');
reg_key_.compile(reg_key_);
let searchResult = searchChilren(reg_key_, sourcelist);
console.log("searchResult\n"+JSON.stringify(searchResult));
document.getElementById("txtarea").innerHTML="输出:"+JSON.stringify(searchResult);
}
 
function searchChilren(reg_key, list){
    let new_list = new Array();
    for (let index = 0; index < list.length; index++) {
        const element = list[index];
       let obj  = {};
	   let s_lst = [];
	  copyNotArray(obj, element);
	  if(element.children.length > 0 ){//子
            s_lst = searchChilren(reg_key, element.children);
       }
        if(reg_key.test(element.name) || (s_lst.length > 0) ){//比较逻辑
            obj['children'] = s_lst;
            new_list.push(obj);
        }
	}
      
	return new_list;
}
function copyNotArray(toObj, obj){
	for(key in obj){
		let type = obj[key];
	if( !Array.isArray(type) )
		toObj[key] = obj[key]
	}
}
 

vol 2

 var html = "";
for (let index = 0; index < this.user_directory.length; index++) {
    var t = "";
    const element = this.user_directory[index];
    let add = "<div ng-re-id='" + element.id + "' data-name='" + element.name + "'>";
    add += "<div class='operate-col3_div></div>";
    add += "<ul class='ng-scope'>";
    if (element.child.length > 0) {
        t = searchBuildTree(element.child, reg, 2);
        add += t;
    }
    add += "</ul></div>";
    if (!reg.test(element.name) && t == "") {
        add = "";
    }
    html += add;
}
$(data_container).html(html);
$(data_container).show();
 
function searchBuildTree(obj, reg, deep) {
	let html = "";
	for (let index = 0; index < obj.length; index++) {
		let add = ""
		let t = "";
		const element = obj[index];
		add += "<li ng-repeat='fo-" + deep + "' data-uniq-id='" + element.id 
		if (element.child.length > 0) {
			t = searchBuildTree(element.child, reg, (deep + 1));
			add += t;
		}
		add += "</ul> </li>";
		if (!reg.test(element.name) && t == "") {
			add = "";
		}
		html += add;
	}
	return html;
}
 

中英数字 混合排序排序

    sortChinese(data_arr, 'name');
      function sortChinese (arr, dataLeven) { // 参数: arr 排序的数组; dataLeven 数组内的需要比较的元素属性
        
        function getValue (option) { // 参数: option 数组元素
            if (!dataLeven) return option
                var data = option
                dataLeven.split('.').filter(function (item) {
                    data = data[item]
                })
                return data + ''
            }
            arr.sort(function (item1, item2) {
            return getValue(item1).localeCompare(getValue(item2), 'zh-CN');
        })
    }

如何判断Json 点是[] 还是 {}?

var a = [];
a.constructor === Array && a.constructor === Object

TypeScript ---------------------

为旧Vue项目添加ts支持

安装 npm install typescript ts-loader -D

修改 vue.config.js

 configureWebpack: config => {
    const configNew = {}
    if (process.env.NODE_ENV === 'production') {
   
    }else{
      config.resolve.extensions.push('.ts');   // 添加ts扩展文件:引用ts文件的时候不用写后缀名
      config.module.rules.push({             // 使用ts-loader对ts/tsx文件打包编译
        test: /\.tsx?$/,
        loader: 'ts-loader',
        exclude: /node_modules/,
        options: {
          appendTsSuffixTo: [/\.vue$/],    // ts编译器tsc不能识别.vue文件,所以在 .vue文件后加.ts后缀
        },
      });
    }
    return configNew
  },
 

忽略语法检查

@ts-ignore 增加 @ts-ignore 的注释,会忽略下一行的语法检查。

优雅的处理 null

可选链 ?.

?. 遇到 null 或 undefined 就可以立即停止某些表达式的运行,并返回 undefined