js 笔记整理

Js中for、for-in、forEach以及for-of的用法及特性对比

for-in

for...in以任意顺序遍历一个对象的可枚举属性。所以for-in不适合用来迭代一个Array。同时,for-in是可以遍历对象中所有可枚举属性的,包括原型链上的可枚举属性。

let ret = [];
array.num = 6;  //  对象上直接添加属性
Array.prototype.num = 6;  // 原型链中添加属性
for(let i in array){
  ret.push(array[i])
}
console.log(ret)   //  [ 1, 2, 3, 4, 5, 6, 7 ]

  

如果可以地设置属性为不可枚举,那么for-in循环将不会遍历到这个属性

 

let ret = [];
Object.defineProperty(array,"num",{
  enumerable: false,  // 设置属性不可遍历
  value: 8
})
for(let i in array){
  ret.push(array[i])
}
console.log(ret)  //  [ 1, 2, 3, 4, 5 ]

 

解决方法:使用hasOwnProperty()
hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中。这个方法只在给定属性存在于对象实例中时,才会返回true。 

/数组
var arr = ["星期一","星期二","星期三"];
Array.prototype.something = ["放假","休息咯"];
for (var i in arr){
	if(arr.hasOwnProperty(i)){ 
		console.log(arr[i])
	}
}

  

for(最原始的写法)、 支持 break、continue和return语句)、

forEach 数组的方法,arr.forEach;  forEach(ES5,但是它不支持使用break、continue和return语句)、

for…in循环数组索引、对象的属性,但使用 for…in 原型链上的所有属性都将被访问,用 hasOwnProperty() 方法解决。

for…of(ES6,循环数组的元素值)这三个是循环数组(对象数组)的;

定义变量的6种方式

ES5 只有两种声明变量的方法:

var命令和function命令。

ES6 除了添加letconst命令,

还有 import命令和class命令。

 

 

去重两种方式

方法一 分析

function unique(arr) {
    //定义常量 res,值为一个Map对象实例
    const res = new Map();
    
    //返回arr数组过滤后的结果,结果为一个数组
    //过滤条件是,如果res中没有某个键,就设置这个键的值为1
    return arr.filter((a) => !res.has(a) && res.set(a, 1))
}

 

方法二:

 
function unique(arr) {
    return Array.from(new Set(arr))
}

两种还是有差异的,比如[2,,3,3]==>[2,3]/[2,3,undefined]

-----------------------

不指定字段去  es6 new Set 有缺陷,无法过滤 null,undefined

function myseta(ary) {
				const strings = ary.map((item) => JSON.stringify(item))
				// 使用Set数据结构去重对象
				// return new Set(strings)
				//var arr6 = [null, "null", undefined, "undefined", "", NaN, null, , undefined, , , NaN, ""]
				//console.log("strings", strings)
				//	 ['null', '"null"', undefined, '"undefined"', '""', 'null', undefined]

				// 使用Array.from()把Set数据结构去重对象后的结构,转为数组
				// return Array.from(new Set(strings))
				//报错 JSON.parse(item)  "undefined" is not valid JSON
				// 使用Array.from()转为数组,然后再使用数组的map方法把数组里面的字符串类型转化为对象类型:
				return Array.from(new Set(strings)).map((item) => JSON.parse(item))

			};

  

特别注意下面可,完美 过滤null,NaN,undefined,{}

 

	function normalarr(array, index) {
					// var arr5 =[1, 2, 0, 0, null, "null", false, "false", {"id": 1}, {"id": 2}, {"id": 1},5, "5", {}, {}]
					// var arr6 = [null, "null", undefined, "undefined", "", NaN, null, , undefined, , , NaN, ""]
					// var arr7 = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN,
					// 	'NaN', 0, 0, 'a', 'a', {}, {}
					// ]
					//console.log("去重arr5   ", unique(arr5))
					//[[1, 2, 0, null, 'null', false, 'false', {id: 1}, {id: 2}, 5, '5', {}]]
					//console.log("去重arr6  ", unique(arr6))
					//[null, 'null', undefined, 'undefined', '', NaN]
					//console.log("去重arr7  ", unique(arr7))
					//[1, 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {}]
					var obj = {};
					return array.filter(function(item, index) {
						//console.log("typeof item + item", typeof item + JSON.stringify(item))
						var hasOne = typeof item + JSON.stringify(item)
						return obj.hasOwnProperty(hasOne) ? 0 : (obj[hasOne] = 1) //已存在则过滤,不然就新增属性
					})
				}

 

  

 

  

字段去重 指定与不指定 两者封装

function unique(array, prop) {
				var len = array && array.length;
				if (!len) {
					return [];
				}
				var util = {
					isObject: function(value) {
						return Object.prototype.toString.call(value) === '[object Object]';
					}
				}

				function normalarr(array, index) {
					// var arr5 =[1, 2, 0, 0, null, "null", false, "false", {"id": 1}, {"id": 2}, {"id": 1},5, "5", {}, {}]
					// var arr6 = [null, "null", undefined, "undefined", "", NaN, null, , undefined, , , NaN, ""]
					// var arr7 = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN,
					// 	'NaN', 0, 0, 'a', 'a', {}, {}
					// ]
					//console.log("去重arr5   ", unique(arr5))
					//[[1, 2, 0, null, 'null', false, 'false', {id: 1}, {id: 2}, 5, '5', {}]]
					//console.log("去重arr6  ", unique(arr6))
					//[null, 'null', undefined, 'undefined', '', NaN]
					//console.log("去重arr7  ", unique(arr7))
					//[1, 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {}]
					var obj = {};
					return array.filter(function(item, index) {
						//console.log("typeof item + item", typeof item + JSON.stringify(item))
						var hasOne = typeof item + JSON.stringify(item)
						return obj.hasOwnProperty(hasOne) ? 0 : (obj[hasOne] = 1) //已存在则过滤,不然就新增属性
					})
				}

				function uuidarr(array, prop) {
					// var ary1 = [
					// 	{id: 0,text: 0},
					// 	{id: 1,text: "1"}, 
					// 	{id: 1,text: "1"}, 
					// 	{id: 2,text: "2"},
					// 	{id: '',text: ''},
					// 	{id: true,text: true},
					// 	{id: null,text: null},
					// 	{id: NaN,text: NaN},
					// 	{id: undefined,text: undefined},
					// 	{id: "true",text: "true"},
					// 	{id: "null",text: null},
					// 	{id: "NaN",text: NaN},
					// 	{id: "undefined",text: undefined},
					// ];
					var result = [];
					var obj = {};
					var len = array.length;
					for (var i = 0; i < len; i++) {
						var oneitem = array[i];
						if (util.isObject(oneitem) && oneitem.hasOwnProperty(prop)) {
							var oneVal = oneitem[prop];
							//区分 字符串 [null,NaN, undefined,"null","NaN","undefined"]
							//var keyOne =oneVal;无法区分字符串  null 与 "null"  NaN 与 "NaN" undefined 与 "undefined"
							var keyOne = typeof oneVal + oneVal;
							if (!obj[keyOne]) {
								result.push(oneitem);
								obj[keyOne] = 1;
							}
						}
					}
					return result;
				}

				if (typeof prop === "undefined") {
					return normalarr(array)
				}
				return uuidarr(array, prop)
			}

  

 

数组中存在某个字段

function inArray(elem, array, i) {

				var util = {
					isNaN: function(value) {
						return value !== value
					},
					isObject: function(value) {
						return Object.prototype.toString.call(value) === '[object Object]';
					},
				}

				//  var array = []; arr[2] = 1;
				//  var array = [null, '', NaN, undefined, {}, "null", "undefined", "NaN", "{}", {id: 1}, {id: 2}, {id: 1}]

				// console.log(" null        inArray", inArray(null, array))
				// console.log(" ''          inArray", inArray('', array))
				// console.log(" NaN         inArray", inArray(NaN, array))
				// console.log(" undefined   inArray", inArray(undefined, array))
				// console.log(" {}          inArray", inArray({}, array))

				// console.log("'null'       inArray", inArray('null', array))
				// console.log("'undefined'  inArray", inArray("undefined", array))
				// console.log("'NaN'        inArray", inArray('NaN', array))
				// console.log("'{}'         inArray", inArray('{}', array))

				// console.log(" {id:1}      inArray", inArray({
				// 	id: 1,
				// }, array))
				// console.log(" {id:2}      inArray", inArray({
				// 	id: 2,
				// }, array))
				// console.log("'test' inArray", inArray("test", array))
				var len = array && array.length;
				var i = i ? i < 0 ? Math.max(0, len + i) : i : 0; // 当i为负数时,从数组后边len+i的位置开始索引;当i不存在时,从数组首元素开始检索;
				if (!len) {
					return -1;
				}
				// console.log("i", i)
				if (!util.isNaN(elem) && !util.isObject(elem) && typeof elem !== 'undefined' && array.indexOf) {
					//console.log("indexOf")
					//1,array.indexOf 无法区分 NaN、{} ;2,array.indexOf(empty)返回-1
					//var arr0 = [];arr0[2] = 1;  此时 arr0 =[empty × 2, 1]  array.indexOf(arr0[0]) 查找为-1
					return array.indexOf(elem)
				}

				for (; i < len; i++) {
					var oneitem = array[i];
					//console.log(oneitem, "i in arr", i in array)

					if (util.isNaN(elem)) {
						if (util.isNaN(elem) === util.isNaN(oneitem)) {
							//console.log("isNaN", i)
							return i;
						}

					} else if (util.isObject(elem)) {

						if (JSON.stringify(elem) === JSON.stringify(oneitem)) {
							//console.log("obj", i)
							return i;
						}
					} else if (elem === oneitem) {
						//console.log("其他", i)
						return i;
					}
				}
				//没有找到的话就返回-1  
				return -1;

			}

  

  

 

 

数组去交集

		// 原数组
		const serveralArr = [
		[1,2,2,5,3],
		[3,2,3,2,2],
		[3,2,4,4],
		[3],
		]
		// 取交集
		function intersectRepeat(arr){
				
		var result= arr.reduce((a, b) => a.filter(c => b.includes(c))) // [4]
		    result= Array.from(new Set(result))
		return result
		
		}
		console.log("交集结果 是:",intersectRepeat(serveralArr)) //  [2, 3]

  

 

 

变量作用域常见问题

//例如,以下代码会输出5次,结果都是5,那么如何输出0、1、2、3、4?
 
 for(var i = 0; i < 5; i++) {
       setTimeout(function() {
              console.log(i);
        }, 1000);
 }
//利用闭包的原理实现,代码如下:
 
 for(var i = 0; i < 5; i++) {
         (function(e) {
                setTimeout(function() {
                    console.log('传进来的是'+e);
                }, 1000);
        })(i);
} 

 

for(let i = 0; i < 5; i++) {
       
                setTimeout(function() {
                    console.log('传进来的是'+i);
                }, 1000);
       
} 

  

数组中随机随 指定个数

function getRandomArray(arr,num){
				    //新建一个数组,将传入的数组复制过来,用于运算,而不要直接操作传入的数组;
				    var temp_array = new Array();
				    for (var index in arr) {
				        temp_array.push(arr[index]);
				    }
				    //取出的数值项,保存在此数组
				    var return_array = new Array();
				    for (var i = 0; i<num; i++) {
				        //判断如果数组还有可以取出的元素,以防下标越界
				        if (temp_array.length>0) {
				            //在数组中产生一个随机索引
				            var arrIndex = Math.floor(Math.random()*temp_array.length);
				            //将此随机索引的对应的数组元素值复制出来
				            return_array[i] = temp_array[arrIndex];
				            //然后删掉此索引的数组元素,这时候temp_array变为新的数组
				            temp_array.splice(arrIndex, 1);
				        } else {
				            //数组中数据项取完后,退出循环,比如数组本来只有10项,但要求取出20项.
				            break;
				        }
				    }
				    return return_array;
				}

  

 

es6 字符串

 $("#result").append(
        `He is <b>${person.name}</b>and we wish to know his${person.age}.that is all`
        );

  

:prop="`list.${index2}.tableData.${scope.$index}.input`" 

 

 

js 数据类型判断 iview

function typeOf(obj) {
    const toString = Object.prototype.toString;
    const map = {
        '[object Boolean]'  : 'boolean',
        '[object Number]'   : 'number',
        '[object String]'   : 'string',
        '[object Function]' : 'function',
        '[object Array]'    : 'array',
        '[object Date]'     : 'date',
        '[object RegExp]'   : 'regExp',
        '[object Undefined]': 'undefined',
        '[object Null]'     : 'null',
        '[object Object]'   : 'object'
    };
    return map[toString.call(obj)];
}

  

 

es6 剩余参数

function setData(index,howmany){
	           
	         		  var arg=arguments;
	         		  var index=arg[0]; 
	                  var howmany=arg[1];
	         		  var newList =[].slice.call(arguments).filter(function (item,index) {
	                      return index>1;
	                    });

                       //var args = [].slice.call(arguments)
                       // 避免泄露参数 参数是执行数组方法时括号中的参数
                       // http://jsperf.com/closure-with-arguments
                       //  let i = arguments.length
                       //  var args = new Array(i)
                       //  while (i--) {
                       //    args[i] = arguments[i]
                       //  }
                       	         
                       // 从第二个参数开始处理(数组下标1)
                       //	 for (var  i = 2, len = arguments.length; i < len; i++) {
                       //	result[arguments[i]] = object[arguments[i]]
                       //	}
                          
                       // 子类续承父类
                       //Rectangle.prototype = Object.create(Shape.prototype);
                       //Rectangle.prototype.constructor = Rectangle;
}

  

function func(a,b ...rest) {
  console.log(a)
  console.log(rest)
}
func(1)
func(1, 2, 3, 4)

 

<script>
        function func(a) {
             var  normalArray  = [].slice.call(arguments);
            
             var default_len=arguments.callee.length; //获取形参的个数:函数名.length 或 arguments.callee.length
             var option_len=normalArray.length||0;//获取实参的个数:arguments.length
                 console.log('arguments--------------',arguments,)
                 console.log("default_len",default_len,"option_len",option_len,"normalArray",normalArray)
             var first=normalArray.slice(0,default_len);
            
             var rest=normalArray.slice((default_len));
                if(default_len>=option_len){
                    
                  rest=[];
                   console.log("相等",rest)
                }
             console.log("first",first)
             console.log("rest",rest)
         console.log("-------------------------------------------------------------------")
          
        }
        func()
        func(1)
        func(9,8)
        func(2, 6, 3, 4)
    </script>

 

 // ES5
 a = list[0], rest = list.slice(1)

 // ES6
 [a, ...rest] = list

  

 字符串长度

	      function length(str) {
		 return [...str].length;
		}
		
		console.log( length('x\uD83D\uDE80y')) // 3
		console.log(  length('22')) // 2
		console.log(    length('哈哈')) // 2

伪数组转换为数组 

var nodeList = document.querySelectorAll('div');
console.log([...nodeList]);  // [div, div, div ... ]

拆解字符串与数组 

var array = [1,2,3,4];
console.log(...array);//1 2 3 4 
var str = "String";
console.log(...str);//S t r i n g

 数组清空

 

数组中间 插入数组

        <script>
            
            var  arr1=[1,2,3,4,7,8]
            var  arr2=[5,6]
            arr1.splice(4,0,...arr2)
            console.log("arr1",arr1)
            
            var  adrr1=[1,2,3,4,7,8]
            var  adrr2=[5,6]
             adrr1.splice.apply(adrr1,[4,0].concat(adrr2))
                console.log("adrr1",adrr1)
            
            
            var  array1=[1,2,3,4,7,8]
            var  array2=[5,6]
           var nArray1 = array1.slice(0, 4).concat(array2, array1.slice(4));
           var nArray2 = [...array1.slice(0, 4), ...array2, ...array1.slice(4)];

            console.log("nArray1",nArray1)
            console.log("nArray2",nArray2)
            
            
         function insert(arrfirst,arrlast,index){
            if (index < 0){
                index = 0;
            }else if(index > arrfirst.length){
                index = arrfirst.length;
            }
            for (var i = arrlast.length-1; i >= 0; i--){
                arrfirst.splice(index,0,arrlast[i]);//是在index位置用arrlast[i]替换掉arrfirst数组中的0个元素
            }
            return arrfirst;
        }
        var  a1rr1=[1,2,3,4,7,8]
        var  a1rr2=[5,6]
        console.log('insert',insert(a1rr1,a1rr2,4));    

        
        
        </script>

 

替换整个数组   splice 与slice

                       var  ar2r=[1,2,3]
			var  ar3r=[4,5,6]
			     ar2r.splice(0,ar2r.length,...ar3r)
			var  ar6r=ar3r.slice() 
				 console.log("ar2r",ar2r,'ar6r',ar6r,'ar3r',ar3r)//[4,5,6]
			// ar2r  [4, 5, 6] ar6r (3) [4, 5, 6] ar3r (3) [4, 5, 6]

  

 

/**
 * Creates a slice of `array` from `start` up to, but not including, `end`.
 *
 * **Note:** This method is used instead of
 * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
 * returned.
 *
 * @since 3.0.0
 * @category Array
 * @param {Array} array The array to slice.
 * @param {number} [start=0] The start position. A negative index will be treated as an offset from the end.
 * @param {number} [end=array.length] The end position. A negative index will be treated as an offset from the end.
 * @returns {Array} Returns the slice of `array`.
 * @example
 *
 * var array = [1, 2, 3, 4]
 *
 * _.slice(array, 2)
 * // => [3, 4]
 */
function slice(array, start, end) {
    let length = array == null ? 0 : array.length;
    if (!length) {
        return [];
    }
    start = start == null ? 0 : start;
    end = end === undefined ? length : end;

    if (start < 0) {
        start = -start > length ? 0 : length + start;
    }
    end = end > length ? length : end;
    if (end < 0) {
        end += length;
    }
    length = start > end ? 0 : (end - start) >>> 0;
    start >>>= 0;

    let index = -1;
    const result = new Array(length);
    while (++index < length) {
        result[index] = array[index + start];
    }
    return result;
}

export default slice;

 start 是 {},却可以返回空数组而没有报错,秘诀在于使用了 >>>, 这个符号叫做无符号右移操作符,>>>0 作用是保证值是有意义的正整数,若无意义则缺省为 0,这里 {}>>>0 会被转换为 0,因此不会报错。  

 去掉opt里面的 ‘undefined’,‘null ’ 字符串

 Object.keys(opt).forEach(key => {
      if (opt[key]&&(opt[key]=="undefined"||opt[key]=="null")) {
          opt[key]="";
      }
      })

 

 

 function deleteEmptyProp(opt,delArr,del) {
               var delArr=delArr||["undefined","null",undefined,null,NaN];
               for (var key in opt) {
                    var val=opt[key];
                    
                        if (delArr.includes(val)) {
                               if(del){
                                    delete opt[key]; 
                               }else{
                                   var isValueNaN= (typeof val === 'number')&&(val !== val)?1:0;//判断NaN ,替换成0
                                   if(isValueNaN){
                                       opt[key]=0;    
                                   }else{
                                       opt[key]="";   
                                   }
                                    
                               }
                        
                        }
               }
               return opt;
           }


            var sas={a: 'duo1', b: 0, c: null,d:"null",e:"undefined",f:NaN,g:undefined}
            console.log((deleteEmptyProp(sas)))
            
            var sas2={a: 'duo2', b: 0, c: null,d:"null",e:"undefined",f:NaN,g:undefined,h:"NaN"}
            console.log(deleteEmptyProp(sas2,["undefined","null","NaN"]))

 

 限制数字两位小数或者正整数

				<input class="uni-input"  v-model="form1Data.aa" @input="handleInput($event,'aa',0)"  placeholder="填写整数" />
					<input class="uni-input"  v-model="form1Data.bb"  @input="handleInput($event,'bb',2)"  placeholder="填写2位小数" />
					<input class="uni-input"  v-model="form1Data.cc"  @input="handleInput($event,'cc','int')"  placeholder="整数不设置min 空开始,1有效" />
					<input class="uni-input"  v-model="form1Data.dd"  @input="handleInput($event,'dd','int',{min:0})"  placeholder="整数设置 0开始  " />
					<input class="uni-input"  v-model="form1Data.ee"  @input="handleInput($event,'ee','int',{min:1})"  placeholder="整数设置 1开始" />
					<input class="uni-input"  v-model="form1Data.ff"  @input="handleInput($event,'ff','int',{min:3,max:5})"  placeholder="整数设置  3开始,最大5" />
					

  

 

使用

handleInput(e,prop,len,minAndMaxOut){
				
				//正则表达试
				var  len=len||0;
				var  val=e.detail&&e.detail.value||e.target&&e.target.value||e;
				  
	 			  if (val!="") {
					   //console.log("handleInput "+prop,"--val--",val,typeof val) 
						
						if(len==0||len=="int"||len=="integer"){
							   //console.log("正整数",val);
							
                           var isObj= Object.prototype.toString.call(minAndMaxOut) === '[object Object]'
							if(isObj){
								val =parseInt(val||0);
								var minAndMax={min:"",max:""}//
							        minAndMax={...minAndMax,...minAndMaxOut}
			
									if(val!=""&&val<parseInt(minAndMax.min)){
									   val=minAndMax.min
									}
									if(val!=""&&val>parseInt(minAndMax.max)){
									   val=minAndMax.max
									}
									
									if(val==0&&val<minAndMax.min){
										 //console.log(val,"数字0 的处理")
									     val=minAndMax.min
									}
							}else{
								  val =parseInt(val||0)||"";  
							}
							
							
							
						}else{
						 //console.log("正小数",val);
						
	 			        var value=val;
	                        if(typeof value!="string"){
								value=value.toString();
							}
						
						  value =value.replace(/[^\d.]/g,""); //清除"数字"和"."以外的字符
						  value =value.replace(/^\./g,""); //验证第一个字符是数字
						  value =value.replace(/\.{2,}/g,"."); //只保留第一个, 清除多余的
						  value =value.replace(".","$#$").replace(/\./g,"").replace("$#$",".");//限制"10.5." 这种情况
						  value =value.replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3'); //只能输入两个小数

				        	if (value.indexOf(".") < 0 && value != "") { 
				       		   value = parseFloat(value);
				        	}
							
	
     			          val=value;
					   }
	
	 			}
				
				 
				//重新赋值给input
				this.$nextTick(() => {
					if(val !== val){//值是为NaN
						val="";
					}
					
					this.formData[prop]= val
					// console.log("最后 val",val,"this.form1Data."+prop,this.form1Data[prop]);
				})
	
			},

  

  

 对象拷贝 浅一层深拷贝 es5的 Object.assign({},objNew) 与 es6的  {...{},...objNew} 一样

<script>
            var target0 = {
                name: '0带你飞'
            }

            var result0 = Object.assign(target0)
            result0.name = "0新名字"
            console.log("Object.assign   =>(target) 覆盖 旧的target", target0, '新的', result0)
            //覆盖 旧的target {name: '0新名字'} 新的 {name: '0新名字'}


            var target1 = {
                name: '1带你飞'
            }

            var result1 = Object.assign({}, target1)
            result1.name = "1新名字"
            console.log(" Object.assign  =>({}, target) 拷贝 旧的target", target1, '新的', result1)
            //拷贝 旧的target {name: '1带你飞'} 新的 {name: '1新名字'}


            console.log("---------------------------")
            let person1 = {
                key: {
                    age: '旧1的'
                }
            }
            let res1 = Object.assign({}, person1)
            res1.key.age = "新1的" + 18
            console.log("拷贝第2层浅拷贝 ", "", person1, "", res1)
            //拷贝第2层浅拷贝  旧 {key: {age: '新1的18'}  新 {key: {age: '新1的18'}


            // 深拷贝
            let person2 = {
                key: {
                    name: '旧1的'
                }
            }
            let res2 = Object.assign({}, person2)
            res2.key = "新2的" + 28
            console.log("拷贝第1层深拷贝 ", "", person2, "", res2)
            //拷贝第1层深拷贝  旧 {key: {name: '旧1的'}} 新 {key: '新2的28'}

            var objnew11 = {
                name: "1旧的第一层"
            }
            var objnew22 = {
                name: "2旧的第一层"
            }
            var copy11 = Object.assign({}, objnew11)
            var copy22 = {
                ...{},
                ...objnew22
            }
            copy11.name = "新的第1层"
            copy22.name = "新的第2层"
            console.log("copy11=Object.assign({},objnew11)形式----objnew11", objnew11, "新的", copy11)
            //copy11=Object.assign({},objnew11)形式----objnew11 {name: '1旧的第一层'} 新的 {name: '新的第1层'}
            console.log("copy22={...{},...objnew22}形式 -----objnew22", objnew22, "新的", copy22)
            //copy22={...{},...objnew22}形式 -----objnew22 {name: '2旧的第一层'} 新的 {name: '新的第2层'}
        </script>

结果:

 


数组浅拷贝

const arr = [1,2,3]
const copyArr = [...arr]

  

var arr1 = [1,2,3]
var arr2 = arr1.slice()  // 方法一
// var arr2 = arr1.concat()  //方法二
arr2.push(4)
console.log('arr1:', arr1)  // arr1: [1, 2, 3]
console.log('arr2:', arr2)  // arr1: [1, 2, 3, 4]

  

深拷贝

function deepClone1(obj) {
	return JSON.parse(JSON.stringify(obj));
}

function deepClone(obj) { //

	if (obj === null) return obj
	//if ([null, undefined, NaN, false].includes(obj)) return obj;
	if (typeof obj == 'function') return new Function('return ' + obj.toString())()
	if (typeof obj != 'object') return obj
	if (obj instanceof RegExp) return new RegExp(obj)
	if (obj instanceof Date) return new Date(obj)
	// 运行到这里,基本上只存在数组和对象两种类型了
	let newObj = Object.prototype.toString.call(obj) === '[object Array]' ? [] : {};
	for (let index in obj) {
		newObj[index] = deepClone(obj[index]); // 对子项进行递归复制
	}
	return newObj;
}



// 深度克隆
function deepClone3(obj) {
	// 对常见的“非”值,直接返回原来值
	if ([null, undefined, NaN, false].includes(obj)) return obj;
	if (typeof obj !== "object" && typeof obj !== 'function') {
		//原始类型直接返回
		return obj;
	}
	var o = Object.prototype.toString.call(obj) === '[object Array]' ? [] : {};
	for (let i in obj) {
		if (obj.hasOwnProperty(i)) {
			o[i] = typeof obj[i] === "object" ? deepClone3(obj[i]) : obj[i];
		}
	}
	return o;
} 

测试数据

let obj = {
	a: 1,
	arr: [1, 3, 5, 7, 9],
	c: {
		num: 100
	},
	fn: function() {
		console.log(1)
	},
	date: new Date(),
	reg: /\.*/g,
	aa: null,
	bb: undefined,
	cc: NaN,
	dd: false
}
console.log("原始", (obj))
console.log("deepClone1", deepClone1(obj))
console.log("deepClone", deepClone(obj))
console.log("deepClone3", deepClone3(obj)) 

测试结果

 

合并对象

function myExtend() {
        var length = arguments.length;
        var target = arguments[0] || {};
        if (typeof target!="object" && typeof target != "function") {
            target = {};
        }
        if (length == 1) {
            target = this;
            i--;
        }
        for (var i = 1; i < length; i++) {
            var source = arguments[i];
            for (var key in source) {
                // 使用for in会遍历数组所有的可枚举属性,包括原型。
                if (Object.prototype.hasOwnProperty.call(source, key)) {
                    target[key] = source[key];
                }
            }
        }
        return target;
    }

 简单合并对象

//var    obj3= {...{},...obj1,...obj2 }
//var   obj3 =Object.assign({},obj1,obj2)
//var    obj3= myExtend({},obj1,obj2)

 

var person1 = {
  name: '小明',
  age: 18,
  sex: '男',
}
var hobby = {
  music: '伤感类歌曲',
  like: '吃饭、睡觉、打游戏',
}
var xiaoHong = {
  ...person1,
  ...{name: '小红',sex:'女'},
  ...hobby
}
console.log(xiaoHong)
// 输出:{name: "小红", age: 18, sex: "女", music: "伤感类歌曲", like: "吃饭、睡觉、打游戏"}

  

jquery 版本

function myExtend2() {

				function isArray(arr) {
					return Object.prototype.toString.call(arr) === '[object Array]';
				}

				function isFunction(arr) {
					return Object.prototype.toString.call(arr) === '[object Function]';
				}

				function isPlainObject(arr) {
					return Object.prototype.toString.call(arr) === '[object Object]';
				}

				var options, name, src, copy, copyIsArray, clone,
					target = arguments[0] || {},
					i = 1,
					length = arguments.length,
					deep = true;

				if (typeof target === "boolean") {
			  deep = target;
					target = arguments[1] || {};
					i = 2;
				}



				if (typeof target !== "object" && !isFunction(target)) {
					target = {};
				}

				if (length === i) {
					target = this;
					--i;
				}

				for (; i < length; i++) {
					if ((options = arguments[i]) != null) {
						for (name in options) {
							src = target[name];
			  		copy = options[name];

							if (target === copy) {
								continue;
							}

							if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
								if (copyIsArray) {
									copyIsArray = false;
									clone = src && isArray(src) ? src : [];
								} else {
									clone = src && isPlainObject(src) ? src : {};
								}

								target[name] = myExtend2(deep, clone, copy);

							} else if (copy !== undefined) {
								target[name] = copy;
							}
						}
					}
				}

				return target;
			}


			var obj1 = {
				a: 1,
				name: "张珊",
				title: {
					text: 'hello world',
					subtext: 'It/s my world.'
				}
			};
			var obj2 = {
				a: 2,
				name: "李四",
				title: {
					subtext: 'Yes, your world.'
				}
			}

			//var    obj3= {...{},...obj1,...obj2 }
			// Object.assign(目标对象,...源对象)可以有多个源对象
			//var obj3 =Object.assign({},obj1,obj2)
			//var    obj3= myExtend({},obj1,obj2)
		
			//console.log("$",$.version)
			//var    obj3= $.extend(true,{},obj1,obj2)
			//var    obj3= myExtend({},obj1,obj2)
			var obj3 = myExtend2({}, obj1, obj2)


			obj3.name = '王五'
			console.log("obj1", obj1);
			console.log("obj2", obj2);
			console.log("obj3", obj3, "title", obj3.title);

  

 

 

 

那async到底哪里简化了Promise

我们在写Promise操作的时候,经常会把Promise作为一个函数的返回值,如果函数很多,我们就要一直 return new Promise(...) ,这样非常麻烦,既然都要返回Promise,如果有简化操作,岂不是很香嘛?那解决办法就是async~

async function test() {
    return 123;
}

// 上面的代码相当于写成这样
function test() {
	return new Promise((resolve, reject) => {
		resolve(123);
    })
}

 ---

async function mayi() {
    return "1蚂蚁雅黑";
}
async function test() {
    console.log(await mayi());
}
test();

// 上下代码等效

function mayi() {
    return new Promise((resolve, reject) => {
        resolve("1蚂蚁雅黑")
    })
}
function test() {
    return new Promise((resolve, reject) => {
        mayi().then(res => {
            console.log(res)
        })
    })
}
test();

  

 

 

fetch('http://localhost:8088/getInfo?name=clz')
    .then(async (res) => {
        const data = await res.text()
        console.log(data)
        console.log(typeof data)
    })

  

 

for  /while    循环 省略

var cars=["BMW","Volvo","Saab","Ford"];
 
for (var i=cars.length;i--;)
{
    console.log(cars[i] + "<br>");
 
}
 
var cars0=["BMW0","Volvo0","Saab0","Ford0"];
 
for (var i=0;i<cars0.length;i++)
{
    console.log(cars0[i] + "<br>");
 
}
 
 var cars=["BMW1","Volvo1","Saab1","Ford1"];
var i=0;
for (;cars[i];)
{
    console.log(cars[i] + "<br>");
    i++;
}
 
var cars2=["BMW2","Volvo2","Saab2","Ford2"];
var i=0;
while (cars2[i])
{
    console.log(cars2[i] + "<br>");
    i++;
}
 
var cars3=["BMW3","Volvo3","Saab3","Ford3"];
var i=cars3.length;
while (i--)
{
    console.log(cars3[i] + "<br>");
 
}

  

 获取css3 translate 属性

function getTransform(el) {  //获取translate
       var transform =  window.getComputedStyle(el, null).getPropertyValue('-webkit-transform')|| window.getComputedStyle(el, null).getPropertyValue('transform');
       var matrix = transform.match(/matrix(3d)?\((.+?)\)/);
         var is3D = matrix && matrix[1];
         if (matrix) {
             matrix = matrix[2].split(",");
             if (is3D === "3d")
                 matrix = matrix.slice(12, 15);
             else {
                 matrix.push(0);
                 matrix = matrix.slice(4, 7);
             }
         } else {
             matrix = [0, 0, 0];
         }
         var result = [
              Number(matrix[0]),
              Number(matrix[1]),
              Number(matrix[2])
         ];
     console.log("result",result)
         return result;
 }

 

 

 json对象 还是json字符串

 /**
  * 是否json字符串
  */
 function  isJSONStr(value) {
     if (typeof value == 'string') {
         try {
             var obj = JSON.parse(value);
             if (typeof obj == 'object' && obj) {
                 return true;
             } else {
                 return false;
             }
         } catch (e) {
             return false;
         }
     }
     return false;
 }
 
 //https://github.com/lodash/lodash
 function isJSONObj(obj){
  return typeof(obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && !obj.length;
 }

 

 

移动端 键盘事件

onCompositionStart以及onCompositionEnd

  

 两个dom 是否相同

所谓相同,指的是两个节点引用的是同一个对象;

所谓相等,指的是两个节点是否是同一类型,具有相等的属性(nodeName,nodeValue。。。等等),还有相等的attributes,childNodes(相同的位置包含相同的值)

语法:

 

node1.isSameNode(node2) 
node1.isEqualNode(node2)

  

 

formatDate

function formatDate(date) {
  var d = new Date(date),
    month = '' + (d.getMonth() + 1),
    day = '' + d.getDate(),
    year = d.getFullYear();
  
  if (month.length < 2) month = '0' + month;
  if (day.length < 2) day = '0' + day;
  
  return [year, month, day].join('-');
}
 console.log(formatDate('Sun May 13,2016'))

  

toFormatNumber

function  toFormatNumber(event,itemprops,item,minVal){
 
      var item2=item;
      var result= item2[itemprops]||"";
            result = result.toString().replace(/[^\d.]/g,"");  //清除“数字”和“.”以外的字符 
              result = result.replace(/\.{2,}/g,"."); //只保留第一个. 清除多余的 
          result = result.replace(".","$#$").replace(/\./g,"").replace("$#$",".");
          result= result.replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3');//只能输入两个小数 
            if(result.indexOf(".")< 0 && result !=""){//以上已经过滤,此处如果没有小数点,首位不能为类似于 01、02的金额
                result= parseFloat(result);
            }
             
 
            if(minVal&&result<minVal){
                result=minVal;
    }
        this.$set(item2,itemprops,result);
    };
 

数组字符串

var str2 = "0123456789";
console.log(str2.slice(4,7));       //----------"456"
 
var arrs=[0,1,2,3,4,5,6,7,8,9];
console.log(arrs.slice(4,7));   //----------"[4,5,6]"

var test = 'hello world';
console.log(test.slice(4,7));             //o w
console.log(test.substring(4,7));         //o w
console.log(test.substr(4,7));            //o world
 
//需要注意的地方就是:substring是以两个参数中较小一个作为起始位置,较大的参数作为结束位置。
console.log(test.substring(7,4))

 

变量 提升 作用域

var msg1='This is message 1';  
var msg3='This is message 3';  
function otherFunction()  
{  
    msg2='This is message 2'; //不使用var关键字,-其实也是定义一个全局变量  
    var msg3='Message 3';  
    var ms4='Message 4';
    alert(msg1); //This is message 1 (-函数内当然可以访问到外面定义的全局变量,再深的函数嵌套一样能正确获到这个全局变量,这是JavaScript闭包的其中一种体现)  
    alert(msg3); //Message 3 (局部变量msg3)  
    alert(window.msg3); //This is message 3 (-使用window前缀访问同名的全局变量msg3)  
    alert(this.msg3); //This is message 3 (-因为otherFunction ()定义在一个全局的环境中,此时otherFunction ()的this也是指向window,所有你看到window. msg3是等于this. msg3的)  
}  
otherFunction();  
//otherFunction-函数外面定义的msg1和里面定义的msg2依然是全局变量  
alert(window.msg1); //-- This is message 1  
alert(window.msg2); //-- This is message 2  
alert(window.ms4); // -- underfind       外部不可以访问内部

 new操作符创建对象

 一般来说,new操作符创建对象可以分为四个步骤:
1. 创建一个空对象
2. 将所创建对象的__proto__属性值设成构造函数的prototype属性值
3. 执行构造函数中的代码,构造函数中的this指向该对象
4. 返回该对象(除非构造函数中返回一个对象)并且最后隐式的返回 this 。
用代码表示如下:

function Person(a, b) {
  this.name = a;
  this.age = b;
}

Person.prototype.show = function() {
  console.log(this.name, this.age);
};

// var p = new Person('address', 10);
var p = {};
p.__proto__ = Person.prototype;
Person.call(p, 'address', 10);

console.log(p);

封装一下 大致如此

function realizeNew () {
    //创建一个新对象
    let obj  = {};
    //获得构造函数
    let Con = [].shift.call(arguments);
    //链接到原型(给obj这个新生对象的原型指向它的构造函数的原型)
    obj.__proto__ = Con.prototype;
    //绑定this
    let result = Con.apply(obj,arguments);
    //确保new出来的是一个对象
    return typeof result === "object" ? result : obj
} 

 

 

js错误类型

Error对象有两个最基本的属性:

name:错误名称
message:错误提示信息

除了Error对象,JavaScript还定义了其他6种错误,即存在Error的6个衍生对象

EvalError:执行代码时发生的错误
RangeError:当一个数值型变量或参数超出有效范围时发生的错误
ReferenceError:引用一个不存在的变量时发生的错误
SyntaxError:解析代码时发生的语法错误
TypeError:变量或参数的类型无效时发生的错误
URIError:向encodeURI() 或者 decodeURI() 传入无效参数时发生的错误

js 命名规范

s:表示字符串。例如:sName,sHtml;
n:表示数字。例如:nPage,nTotal;
b:表示逻辑。例如:bChecked,bHasLogin;
a:表示数组。例如:aList,aGroup;
r:表示正则表达式。例如:rDomain,rEmail;
f:表示函数。例如:fGetHtml,fInit;
o:表示以上未涉及到的其他对象,例如:oButton,oDate;
g:表示全局变量,例如:gUserName,gLoginTime;
 
 

匿名函数写法

 

//五大类
 
//第一类
//最常见的一种
( function(w) {
    alert(w.location.href+","+11);
}(window));
 
[ function(w) {
    alert(w.location.href+","+11);
}(window) ];
 
//第二类
~ function(w) {
    alert(w.location.href+","+11);
}(window);
 
! function(w) {
    alert(w.location.href+","+11);
}(window);
 
+ function(w) {
    alert(w.location.href+","+11);
}(window);
 
- function(w) {
    alert(w.location.href+","+11);
}(window);
 
//第三类
delete function(w) {
    alert(w.location.href+","+11);
}(window);
 
typeof function(w) {
    alert(w.location.href+","+11);
}(window);
 
void function(w) {
    alert(w.location.href+","+11);
}(window);
 
new function(w) {
    alert(w.location.href+","+11);
}(window);
 
new function() {
    alert(window.location.href+","+11);
}; 
 
//第四类
var f = function(w) {
    alert(w.location.href+","+11);
}(window);
 
//第五类
1, function() {
    alert(window.location.href+","+11);
}();
 
1 ^ function() {
    alert(window.location.href+","+11);
}();
 
1 > function() {
    alert(window.location.href+","+11);
}();
 
1 < function() {
    alert(window.location.href+","+11);
}();
 
1 / function() {
    alert(window.location.href+","+11);
}();
 
1 * function() {
    alert(window.location.href+","+11);
}();
 
1 | function() {
    alert(window.location.href+","+11);
}();
 
1 % function() {
    alert(window.location.href+","+11);
}();
 
1 & function() {
    alert(window.location.href+","+11);
}();

 

获取元素尺寸

 /**
    * Get element size
    * @param {HTMLElement} element
    * @returns {Object} {width, height}
    */
    function getElementSize(element) {
        if (!element.getBoundingClientRect) {
            return {
                width: element.offsetWidth,
                height: element.offsetHeight
            }
        }

        var rect = element.getBoundingClientRect();
        return {
            width: Math.round(rect.width),
            height: Math.round(rect.height)
        }
    }

dom 变化2

 

// http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/
(function(){
  var attachEvent = document.attachEvent;
  var isIE = navigator.userAgent.match(/Trident/);
  console.log(isIE);
  var requestFrame = (function(){
    var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
        function(fn){ return window.setTimeout(fn, 20); };
    return function(fn){ return raf(fn); };
  })();
  
  var cancelFrame = (function(){
    var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
           window.clearTimeout;
    return function(id){ return cancel(id); };
  })();
  
  function resizeListener(e){
    var win = e.target || e.srcElement;
    if (win.__resizeRAF__) cancelFrame(win.__resizeRAF__);
    win.__resizeRAF__ = requestFrame(function(){
      var trigger = win.__resizeTrigger__;
      trigger.__resizeListeners__.forEach(function(fn){
        fn.call(trigger, e);
      });
    });
  }
  
  function objectLoad(e){
    this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
    this.contentDocument.defaultView.addEventListener('resize', resizeListener);
  }
  
  window.addResizeListener = function(element, fn){
    if (!element.__resizeListeners__) {
      element.__resizeListeners__ = [];
      if (attachEvent) {
        element.__resizeTrigger__ = element;
        element.attachEvent('onresize', resizeListener);
      }
      else {
        if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
        var obj = element.__resizeTrigger__ = document.createElement('object'); 
        obj.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;');
        obj.__resizeElement__ = element;
        obj.onload = objectLoad;
        obj.type = 'text/html';
        if (isIE) element.appendChild(obj);
        obj.data = 'about:blank';
        if (!isIE) element.appendChild(obj);
      }
    }
    element.__resizeListeners__.push(fn);
  };
  
  window.removeResizeListener = function(element, fn){
    element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
    if (!element.__resizeListeners__.length) {
      if (attachEvent) element.detachEvent('onresize', resizeListener);
      else {
        element.__resizeTrigger__.contentDocument.defaultView.removeEventListener('resize', resizeListener);
        element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__);
      }
    }
  }
})();
//
// var myElement = document.getElementById('my_element'),
//     myResizeFn = function(){
//         /* do something on resize */
//     };
// addResizeListener(myElement, myResizeFn);
// removeResizeListener(myElement, myResizeFn);

  

--

function resizeObserver(ele,fn,self){
	//MutationObserver、IntersectionObserver、ResizeObserver
     var dom=ele;
 	 var self=self||this;;

    // window.ResizeObserver=false;
 	 if(window.ResizeObserver){//resize-observer-polyfill
 	 var myObserver = new ResizeObserver(function(entries) {
		 
		    if(dom.tick){
		     	clearTimeout(dom.tick)
		    }
		    dom.tick=setTimeout(function(){	   					   		
		     	entries.forEach(function(entry){
					entry.offsetHeight=entry.borderBoxSize[0].blockSize||dom&&dom.offsetHeight;
					entry.offsetWidth=entry.borderBoxSize[0].inlineSize||dom&&dom.offsetWidth;
					//console.log("原生 ResizeObserver",entry,'version',self.version)

		     	 	fn&&fn.call(null,entry,self)
		     	  })
		    },12)
 	     })
 		   myObserver.observe(dom)
		 
 		 }else{   // polyfill  兼容处理
			   
			       addResizeListener(ele,function(e){
						var entry={
							offsetHeight:dom.offsetHeight,
							offsetWidth:dom.offsetWidt,
						};
					// console.log("自定义 addResizeListener",entry,'version',self.version)
						fn&&fn.call(null,entry,self)
					})
 		}

 }

  

 

监听dom 变化

//ResizeSensor.js is part of a huge library, but I reduced its functionality to THIS:
 //https://stackoverflow.com/questions/6492683/how-to-detect-divs-dimension-changed/19418065#19418065
 //var container = document.querySelector(".container");
// new ResizeSensor(container, function()
// {
//     console.log("dimension changed:", container.clientWidth, container.clientHeight);
// });



 function ResizeSensor(element, callback)
 {
     var zIndex = parseInt(getComputedStyle(element));
     if(isNaN(zIndex)) { zIndex = 0; };
     zIndex--;
 
     var expand = document.createElement('div');

     // expand.style.position = "absolute";
     // expand.style.left = "0px";
     // expand.style.top = "0px";
     // expand.style.right = "0px";
     // expand.style.bottom = "0px";
     // expand.style.overflow = "hidden";
     // expand.style.zIndex = zIndex;
     // expand.style.visibility = "hidden";
	 
	 setStyle(expand,{
	 	"position":"absolute",
	 	"left":"0px",
	 	"top":"0px",
	 	"right":"0px",
	 	"bottom":"0px",
		"overflow":"hidden",
	 	"zIndex":zIndex,
	 	"visibility":"hidden",
	 })
 
     var expandChild = document.createElement('div');
     // expandChild.style.position = "absolute";
     // expandChild.style.left = "0px";
     // expandChild.style.top = "0px";
     // expandChild.style.width = "10000000px";
     // expandChild.style.height = "10000000px";
	 
	 setStyle(expandChild,{
	 	"position":"absolute",
	 	"left":"0px",
	 	"top":"0px",
	 	"width":"10000000px",
	 	"height":"10000000px",
	 })
	 
     expand.appendChild(expandChild);
	 

     var shrink = document.createElement('div');
     // shrink.style.position = "absolute";
     // shrink.style.left = "0px";
     // shrink.style.top = "0px";
     // shrink.style.right = "0px";
     // shrink.style.bottom = "0px";
     // shrink.style.overflow = "hidden";
     // shrink.style.zIndex = zIndex;
     // shrink.style.visibility = "hidden";
	 
	 setStyle(shrink,{
	 	"position":"absolute",
	 	"left":"0px",
	 	"top":"0px",
	 	"right":"0px",
	 	"bottom":"0px",
	    "overflow":"hidden",
	 	"zIndex":zIndex,
	 	"visibility":"hidden",
	 })
	 

     var shrinkChild = document.createElement('div');
     // shrinkChild.style.position = "absolute";
     // shrinkChild.style.left = "0px";
     // shrinkChild.style.top = "0px";
     // shrinkChild.style.width = "200%";
     // shrinkChild.style.height = "200%";
	 
	 setStyle(shrinkChild,{
	 	"position":"absolute",
	 	"left":"0px",
	 	"top":"0px",
	 	"width":"200%",
	 	"height":"200%",
	 })
	 
	 
	 
     shrink.appendChild(shrinkChild);
 
     element.appendChild(expand);
     element.appendChild(shrink);
 
     function setScroll()
     {
         expand.scrollLeft = 10000000;
         expand.scrollTop = 10000000;
 
         shrink.scrollLeft = 10000000;
         shrink.scrollTop = 10000000;
     };
     setScroll();
 
     var size = element.getBoundingClientRect();
 
     var currentWidth = size.width;
     var currentHeight = size.height;
 
     var onScroll = function()
     {
         var size = element.getBoundingClientRect();
         var newWidth = size.width;
         var newHeight = size.height;
        
         if(newWidth != currentWidth || newHeight != currentHeight)
         {
             currentWidth = newWidth;
             currentHeight = newHeight;
 
             size.height=size.height||size.bottom - size.top||element.offsetHeight;
             size.width=size.width||size.right - size.left||element.offsetWidth;
			 // console.log("element",element)
			 // size.scrollTop=this.scrollTop;
             callback(size);
			
			
         }
 
         setScroll();
     };
 
     expand.addEventListener('scroll', onScroll);
     shrink.addEventListener('scroll', onScroll);
	 function setStyle(eleObj, cssObj) {
	        for (var property in cssObj) {
	            eleObj.style[property] = cssObj[property];
	        };
	  }
 };
 
 
 
 

  

 调用

function resizeObserver(ele,fn,self,timer){
	//MutationObserver、IntersectionObserver、ResizeObserver
     var dom=ele;
 	 var self=self||this;;

    // window.ResizeObserver=false;
 	 if(window.ResizeObserver){//resize-observer-polyfill
 	 var myObserver = new ResizeObserver(function(entries) {
		 
		    if(dom.tick){
		     	clearTimeout(dom.tick)
		    }
		    dom.tick=setTimeout(function(){	   					   		
		     	entries.forEach(function(entry){
					
					// 这里的entry.target是DOM节点本身,而entry.contentRect是一个对象,包含了节点的位置属性,如width, height, left, right, bottom, left, x, y等。
					// width:指元素本身的宽度,不包含padding,border值
					// height:指元素本身的高度,不包含padding,border值
					//offsetHeight = content + padding + border = 200 + 20 * 2 + 2 * 2 = 244
					//clientHeight = content + padding = 200 + 20 * 2 = 240
				
					entry.offsetHeight=entry.borderBoxSize[0].blockSize||dom&&dom.offsetHeight;
					entry.offsetWidth=entry.borderBoxSize[0].inlineSize||dom&&dom.offsetWidth;
					//console.log("原生 ResizeObserver",entry,'version',self.version)

		     	 	fn&&fn.call(null,entry,self)
		     	  })
		    },timer||12)
 	     })
 		   myObserver.observe(dom)
		 
 		}else{   // polyfill  兼容处理
			      
			        if(ResizeSensor){
			   					   new ResizeSensor(dom, function(entry){
			   					       if(dom.tick){
			   					          clearTimeout(dom.tick)
			   					       }
			   					       dom.tick=setTimeout(function(){
			   					   		   
											entry.offsetHeight=entry.height||dom&&dom.offsetHeight;;
											entry.offsetWidth=entry.width||dom&&dom.offsetWidth;
											//console.log("我的 ResizeSensor",entry,'version',self.version)
			   					        	fn&&fn.call(null,entry,self) 
			   					       },timer||12)
			                         });
					
			         }else{
				   

						     var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
						     if(MutationObserver){// ie 

								   var MutationObserverConfig={
									   childList: true,
									   subtree: true,
									   characterData: true
								   };
								   var observer=new MutationObserver(function(entry){
									   
									   if(dom.tick){
									    	clearTimeout(dom.tick)
									   }
									   dom.tick=setTimeout(function(){
												entry.offsetHeight=dom.offsetHeight;
												entry.offsetWidth=dom.offsetWidth;
												//console.log("ie MutationObserver",entry,'version',self.version)
												fn&&fn.call(null,entry,self) 
										 },timer||12)
								   });
								   observer.observe(dom,MutationObserverConfig);
								  
								
							 }else{
									// dom.addEventListener("DOMSubtreeModified",function(entry){
									// 	 if(dom.tick){
									// 		 clearTimeout(dom.tick)
									// 	 }
									// 	 dom.tick=setTimeout(function(){
									// 		fn&&fn.call(null,entry,self) 
									// 	 },timer*8||100) 
									// }, false);
								}	
			}
 		}

 }

---

var dom=document.querySelector(".scroll-height");
		        resizeObserver(dom,function(entry,self){
					

					// console.log('2entry', entry)

					    if(entry&&entry.offsetHeight){
				        	var total= 	Math.ceil(entry.offsetHeight)  ;
					        self.maxScrollHeight=total-self.viewHeight;
						    dom.setAttribute("scroll-height",self.maxScrollHeight)
							dom.setAttribute("max-total",total)
						     self.setOneH()
							  // console.log('检测 entry', entry)	
							if(clickTop){
								self.setTop(clickTop);
							}
						  
						
					       // console.log('clickTop',clickTop,'1有1 entry 检测dom 变化',self.maxScrollHeight)
					      }else{
							  //ie 
							   var total=Math.ceil(dom.offsetHeight);
							       self.maxScrollHeight=total-self.viewHeight;
							       dom.setAttribute("scroll-height",self.maxScrollHeight) //ie 不可以设置
								   dom.setAttribute("max-total",total)
								    self.setOneH()
								   if(clickTop){
								   		self.setTop(clickTop);
								   }
								  
							      // console.log('clickTop',clickTop,'0无0 entry  检测dom 变化',self.maxScrollHeight)	 
						  }
					
				},self); 

  

 //MutationObserver、IntersectionObserver、ResizeObserver

intersection-observer-polyfill 

 

  observe(target) {
        if (!arguments.length) {
            throw new TypeError('1 argument required, but only 0 present.');
        }

        if (!(target instanceof Element)) {
            throw new TypeError('parameter 1 is not of type "Element".');
        }

        let targets = this._targets;

        // Do nothing if target is already observed.
        if (targets.has(target)) {
            return;
        }

        // Create new IntersectionObservation instance and assign it
        // to provided target.
        targets.set(target, new IntersectionObservation(target, this));

        // Connect current observer to controller
        // if it wasn't connected yet.
        if (!this.controller.isConnected(this)) {
            this.controller.connect(this);
        }

        // Request the update of observers.
        this.controller.startUpdateCycle();
    }

 

 elementui resize-event.js

import ResizeObserver from 'resize-observer-polyfill';
import { debounce } from 'throttle-debounce';

const isServer = typeof window === 'undefined';

/* istanbul ignore next */
const resizeHandler = function(entries) {
  for (let entry of entries) {
    const listeners = entry.target.__resizeListeners__ || [];
    if (listeners.length) {
      listeners.forEach(fn => {
        fn();
      });
    }
  }
};

/* istanbul ignore next */
export const addResizeListener = function(element, fn) {
  if (isServer) return;
  if (!element.__resizeListeners__) {
    element.__resizeListeners__ = [];
    element.__ro__ = new ResizeObserver(debounce(16, resizeHandler));
    element.__ro__.observe(element);
  }
  element.__resizeListeners__.push(fn);
};

/* istanbul ignore next */
export const removeResizeListener = function(element, fn) {
  if (!element || !element.__resizeListeners__) return;
  element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
  if (!element.__resizeListeners__.length) {
    element.__ro__.disconnect();
  }
};

 使用

//先引入
import { addResizeListener, removeResizeListener } from 'utils/resize-event';

export default {
  mounted(){
    //可以在mounted这个钩子里初始化事件
    addResizeListener(this.$el, this.resizeListener);
  },
  methods:{
    resizeListener(){
      //do something
    }
  },
  //生命周期结束时销毁事件
  destroyed() {
    if (this.resizeListener) removeResizeListener(this.$el, this.resizeListener);
  }
}

  

 

空对象

const isEmpty = function(val) {
  // null or undefined
  if (val == null) return true;

  if (typeof val === 'boolean') return false;

  if (typeof val === 'number') return !val;

  if (val instanceof Error) return val.message === '';

  switch (Object.prototype.toString.call(val)) {
    // String or Array
    case '[object String]':
    case '[object Array]':
      return !val.length;

    // Map or Set or File
    case '[object File]':
    case '[object Map]':
    case '[object Set]': {
      return !val.size;
    }
    // Plain Object
    case '[object Object]': {
      return !Object.keys(val).length;
    }
  }

  return false;
};

 

 数组 比较

    //判断新旧数组 返回新数组相对老数组 增加数据
               function returnAddData(oldArr, newArr) {
               var obj = {};
               var index; //记录新数组中的索引
               for (var i = 0; i < newArr.length; i++) {
				
				  var sam=  oldArr.some(function( item, index, array ){ 
						   return JSON.stringify(newArr[i]) === JSON.stringify(item)
				 })
               if (sam) {
               } else {
               index = i;
               }
               if (index !== undefined) obj[index] = newArr[index];
               }
               return Object.values(obj);
               }
     
				
				
				//判断新旧数组 返回新数组相对老数组删除数据
				function returnDeleteData(oldArr, newArr) {
				var obj = {};
				var index; //记录老数组中的索引
				for (var i = 0; i < oldArr.length; i++) {
				var sam=newArr.some( function( item, index, array ){ 
					    return JSON.stringify(oldArr[i]) === JSON.stringify(item); 
					})
					
					
				if (sam) {
					
				} else {
				index = i;
				}
				if (index !== undefined) obj[index] = oldArr[index];
				}
				return Object.values(obj);
				}

 

js prop 与attr

  • 对于HTML元素本身就带有的固有属性,在处理的时候,使用prop()方法。 prop 原生的,可以看成 dom 看成object 对象,通过  对象.属性   例如 获取id,   element.id
  • 对于HTML元素我们自己自定义的DOM属性,在处理时,使用attr()方法。

 

其他。。。

uni-app

 

 function mySystem() {
       
		var system=uni.getSystemInfoSync();
		var statusBarHeight = system.statusBarHeight //状态栏高度
		var navigatorHeight=44;
		var isAndroid=false;
		
		if(system.system.toLowerCase().indexOf("ios")!=-1) {
		     navigatorHeight=44
			 isAndroid=false;
		 }else {
			isAndroid=true;
		    navigatorHeight=48
		 }
								
		var totalHeight=navigatorHeight+statusBarHeight
		
	
		//https://uniapp.dcloud.net.cn/tutorial/platform.html#preprocessor
		var   platform="";
			 //#ifdef APP-PLUS
			  platform = "APP-PLUS";///**App*/
			  //#endif
			  
			  //#ifdef APP-PLUS-NVUE || APP-NVUE
			  platform = "APP-PLUS-NVUE";///**App nvue*/     	//APP-PLUS-NVUE或APP-NVUE	 App nvue 页面
			  //#endif
			 
			  //#ifdef MP-WEIXIN
			  platform = "MP-WEIXIN";///**微信小程序*/
			  //#endif
			  
			  
		var navInfo={
			system:system,
			statusBarHeight:statusBarHeight,
			navigatorHeight:navigatorHeight,
			totalHeight:totalHeight,
			isAndroid:isAndroid,
			platform:platform,
			windowHeight:system.windowHeight,
			windowWidth:system.windowWidth,
			safeAreaInsetBottom:system.safeAreaInsets.bottom||0,
			
		 }	
		// localStorage&&localStorage.setItem("isAndroid", this.isAndroid)
		// localStorage&&localStorage.setItem("totalHeight", this.totalHeight)
		// localStorage&&localStorage.setItem("platform", platform)
		//console.log("mySystem ",navInfo,"platform",platform)
		return 	navInfo;				
	
}

 

 

function talkTormatTime(timestamp,all ) {
	
	if (!timestamp) {
		return
	}
	
	var date = new Date(timestamp)
	var strLen = timestamp.toString().length
	// 判断时间戳是否不足13位,不足时低位补0,即乘以10的所差位数次方
	if (strLen < 13) {
		var sub = 13 - strLen
		sub = Math.pow(10, sub) // 计算10的n次方
		date = new Date(timestamp * sub)
	}
	
	var nos = 1, bindf = '-';
	var y = date.getFullYear()
	var M = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
	var d = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
	var h = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
	var m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
	var s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
	
	var todayStamp=+new Date;
	var today= new Date(todayStamp)

	if(today.getDate()==date.getDate()){//同一天
		    nos=-1;
		 	//console.log("同一天")
		if(date.getHours()==today.getHours()){//同一小时
			//console.log("同一小时")
			var df=date.getMinutes()
			var tf=today.getMinutes()
		    var sev=Math.abs(df-tf);
			//console.log("分差"+sev+"分钟",tf,df)
			if(sev<=3){//小于3分钟  刚刚
			  nos=-2;	
			}
		}
	}
	var sa2=h + ':' + m
	//console.log("时间-分",sa2  )
	if(all){
		nos=0;
	}
	if(nos == -1){
		return  h + ':' + m ;
	}
	if(nos == -2){
		return  '刚刚' ;
	}
	
	//2022年4月22日 20:13
	return y + "年" + M + "月" + d + '日' + ' ' + h + ':' + m ;
	
}

  

 ----------------------------------------------------------------------

/**
 * @description 进行延时,以达到可以简写代码的目的 比如: await uni.$u.sleep(20)将会阻塞20ms
 * @param {number} value 堵塞时间 单位ms 毫秒
 * @returns {Promise} 返回promise
 */


function sleep(ms) {
    return new Promise(function(resolve, reject) {
        setTimeout(resolve(true), ms|| 30)
    })
}


// sleep(1000).then(() => {
//     console.log(2000)
// })

/**
	 * @desc 格式化手机号码
	 * @param {String} num 手机号码
	 **/
function	numberFormatter(num) {
		return num.length === 11 ? num.replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2') : num;
	}


//-----------nvue------------------------------------------------------------------------


function	getRect (id,vue,useUni,delay){ //ID选择器:#the-id   #可以不要         紧紧支持id
            var  that=vue;//Vue实例才拥有_isVue 属性,在此是避免观测Vue实例对象。
		  	var  id =id;
		
			if(!vue||!vue._isVue){
				console.log("请传入vue 对象")
				//Promise.resolve(false);
				return false;
			}
			var   useUni=useUni||false;
			var   platform="APP-PLUS";

				 //#ifdef APP-PLUS-NVUE || APP-NVUE
				 platform = "APP-NVUE";///**App nvue*/     	//APP-PLUS-NVUE或APP-NVUE	 App nvue 页面
				 //#endif
				 
               if(useUni){
				  platform="APP-PLUS"; 
			   }
			
           //console.log("getRect id",id)
           //console.log("getRect this",JSON.stringify(that))
			if(platform=="APP-PLUS"){////nvue不支持 uni.createSelectorQuery,
			
			         return new Promise(resolve => {
			           setTimeout(() => {     
							var selector=id.indexOf("#")!=-1?id:("#"+id);
							   //console.log("selector ",selector)
							var query = uni.createSelectorQuery().in(that);
								query.select(selector).boundingClientRect(res => {
									          res.methodType='uni';
											   resolve(res)
											//console.log("uni getRect 1得到布局位置信息" , res);
											//res={"id":"as2ss","dataset":{"ref":"as2ss"},"left":12,"right":312,"top":286,"bottom":336,"width":300,"height":50}
											
								 }).exec();
						}, delay||100);
					})
			
			}else{
			
				////#ifdef APP-NVUE
					const dom = weex.requireModule('dom');
					var id2=id.replace("#",'')
					//console.log("id2 ",id2)
					return new Promise(resolve => {
					  setTimeout(() => {     
						         var talkcontent=that.$refs[id2]
								 var result = dom.getComponentRect(talkcontent, res => {
									       res.size.methodType='weex';
										   resolve(res.size)
									     // console.log("weex getRect 2得到布局位置信息" , res);
									 //res.size= {"right":300,"left":0,"width":300,"bottom":71,"top":21,"height":50}
									
									
								 })
						 }, delay||100);
					})
					//// #endif
			}

	}

//<view id="as2ss" ref="as2ss" style="width: 300px; height: 50px; background-color:#666;"> 布局盒子</view>

//async	test_getRect(){
// 	var   size=await  getRect("#as2ss",this,"weex");
// 	console.log("getRect 结果--",size)
// },

//-----------nvue------------------------------------------------------------------------





//https://github.com/umicro/uView/blob/master/uview-ui/libs/function/trim.js

//trim.js
function trim(str,pos ) {
	
	         if(Object.prototype.toString.call(str) != "[object String]"){
				return str; 
			 }
	       
	
			var pos= pos||'botn'
			 if (pos == "botn") {//两侧
			  return str.replace(/(^\s*)|(\s*$)/g,"");
			 } 
			 if (pos == "left") {
				return str.replace(/^\s*/, '');
			 } 
			 if (pos == 'right') {
				return str.replace(/(\s*$)/g, "");
			 } 
			//全部
			return str.replace(/\s+/g, "");
			
}

function typeOf(obj) {
    const toString = Object.prototype.toString;
    const map = {
        '[object Boolean]'  : 'boolean',
        '[object Number]'   : 'number',
        '[object String]'   : 'string',
        '[object Function]' : 'function',
        '[object Array]'    : 'array',
        '[object Date]'     : 'date',
        '[object RegExp]'   : 'regExp',
        '[object Undefined]': 'undefined',
        '[object Null]'     : 'null',
        '[object Object]'   : 'object'
    };
    return map[toString.call(obj)];
}



 // "true"  => true
  // "false" => false
  // "null"  => null
  // "42"    => 42
  // "42.5"  => 42.5
  // "08"    => "08"
  // JSON    => parse if valid
  // String  => self
  function deserializeValue(value) {
    var num
    try {
      return value ?
        value == "true" ||
        ( value == "false" ? false :
          value == "null" ? null :
          !/^0/.test(value) && !isNaN(num = Number(value)) ? num :
          /^[\[\{]/.test(value) ? $.parseJSON(value) :
          value )
        : value
    } catch(e) {
      return value
    }
  }



// firstUpperCase
function firstUpperCase(str) {
    return str.toString()[0].toUpperCase() + str.toString().slice(1);
}

function random(min, max) {
	if (min >= 0 && max > 0 && max >= min) {
		let gab = max - min + 1;
		return Math.floor(Math.random() * gab + min);
	} else {
		return 0;
	}
}

 function unique(arr,prop){
	     if(!arr||!arr.length){
			 return [];
		 }
	
	     if(!prop){
			   return [...new Set(arr)];
		    }
	
         var result = [];
         var obj = {};
         for (var i =0; i<arr.length; i++){
          if (!obj[arr[i][prop]]){
            result.push(arr[i]);
            obj[arr[i][prop]] = true;
          }
         }
    return result;
}



	function getRandomArray(arr,num){
		 
		    var temp_array = new Array();
		    for (var index in arr) {
		        temp_array.push(arr[index]);
		    }
			// console.log("1 getRandomArray arr",arr)
		    //取出的数值项,保存在此数组
		    var return_array = new Array();
		    for (var i = 0; i<num; i++) {
		        //判断如果数组还有可以取出的元素,以防下标越界
		        if (temp_array.length>0) {
		            //在数组中产生一个随机索引
		            var arrIndex = Math.floor(Math.random()*temp_array.length);
		            //将此随机索引的对应的数组元素值复制出来
		            return_array[i] = temp_array[arrIndex];
		            //然后删掉此索引的数组元素,这时候temp_array变为新的数组
		            temp_array.splice(arrIndex, 1);
		        } else {
		            //数组中数据项取完后,退出循环,比如数组本来只有10项,但要求取出20项.
		            break;
		        }
		    }
			// console.log("getRandomArray",return_array)
		    return return_array;
}




  
  
  
  
  
  
  

  
 //------------is----------------------------------------------------------------------------


  /**
   * 判断是否为空
   */
  function isEmpty(value) {
  	switch (typeof value) {
  		case 'undefined':
  			return true;
  		case 'string':
  			if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true;
  			break;
  		case 'boolean':
  			if (!value) return true;
  			break;
  		case 'number':
  			if (0 === value || isNaN(value)) return true;
  			break;
  		case 'object':
  			if (null === value || value.length === 0) return true;
  			for (var i in value) {
  				return false;
  			}
  			return true;
  	}
  	return false;
  }  
 
 

 
  function isEmptyJSON(obj) {
     return  !Object.getOwnPropertyNames(obj).length &&  !Object.getOwnPropertySymbols(obj).length||JSON.stringify(obj) ===  '{}' ;
   }
  

  
  function isHtmlElement(node) {
    return node && node.nodeType === Node.ELEMENT_NODE;
  }
  
 
 /**
  * 是否json字符串
  */
 function  isJSONStr(value) {
 	if (typeof value == 'string') {
 		try {
 			var obj = JSON.parse(value);
 			if (typeof obj == 'object' && obj) {
 				return true;
 			} else {
 				return false;
 			}
 		} catch (e) {
 			return false;
 		}
 	}
 	return false;
 }
 
 //https://github.com/lodash/lodash
 function isJSONObj(obj){
  return typeof(obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && !obj.length;
 }
 
 /**
  * 是否数组
  */
 function isArray(value) {
 	if (typeof Array.isArray === "function") {
 		return Array.isArray(value);
 	} else {
 		return Object.prototype.toString.call(value) === "[object Array]";
 	}
 }
 
 /**
  * 是否对象
  */
 function isObject(value) {
 	return Object.prototype.toString.call(value) === '[object Object]';
 }
 

function isFunction(obj){
	// console.log(isFunction(alert)); true
	// console.log(isFunction(console.log));  true
	// console.log(isFunction('GeeksgorGeeks'));  false
	
	//https://github.com/jashkenas/underscore/blob/master/modules/isFunction.js
	//https://github.com/jashkenas/underscore/tree/master/modules
	//https://github.com/ElemeFE/element/blob/dev/src/utils/types.js
	
	var isFun = (obj) => {
	  return obj && Object.prototype.toString.call(obj) === '[object Function]';
	};

	// Optimize `isFunction` if appropriate. Work around some `typeof` bugs in old
	// v8, IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236).
	var nodelist =document&&document.childNodes;
	if (typeof /./ != 'function' && typeof Int8Array != 'object' && typeof nodelist != 'function') {
	  isFun = function(obj) {
	    return typeof obj == 'function' || false;
	  };
	} 
	
	return  isFun(obj);
}

function isNumber(obj) {  
    return obj === +obj  
}  

function isValueNaN(value) {
	return typeof value === 'number' && isNaN(value)
}

function isValueNaN2(value) {
	return value !== value
}

function isBoolean(obj) {  
    return obj === !!obj  
}  



 
  
 // -------正则 start------------------------------------------------------------------------------------- 
  // https://github.com/validatorjs/validator.js
  var validator={
	  /**
	   * 验证电子邮箱格式
	   */
	   email(value) {
	  	return /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/.test(value);
	  },
	  
	  /**
	   * 验证手机格式
	   */
	   mobile(value) {
	  	return /^1[3-9]\d{9}$/.test(value)
	  },
	  
	  /**
	   * 验证URL格式
	   */
	   url(value) {
	  	return /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w-.\/?%&=]*)?/.test(value)
	  },
	  
	  /**
	   * 验证日期格式
	   */
	   date(value) {
	  	return !/Invalid|NaN/.test(new Date(value).toString())
	  },
 
	  /**
	   * 验证十进制数字
	   */
	   number(value) {
	  	return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
	  },
	  
	  /**
	   * 验证整数
	   */
	   digits(value) {
	  	return /^\d+$/.test(value)
	  },
	  
	  /**
	   * 验证身份证号码
	   */
	   idCard(value) {
	  	return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)
	  },
	  

	  
	  /**
	   * 金额,只允许2位小数
	   */
	   amount(value) {
	  	//金额,只允许保留两位小数
	  	return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value);
	  },
	  
	  /**
	   * 中文
	   */
	   chinese(value) {
	  	var reg = /^[\u4e00-\u9fa5]+$/gi;
	  	return reg.test(value);
	  },
	  
	  /**
	   * 只能输入字母
	   */
	   letter(value) {
	  	return /^[a-zA-Z]*$/.test(value);
	  },
	  
	  /**
	   * 只能是字母或者数字
	   */
	   enOrNum(value) {
	  	//英文或者数字
	  	var reg = /^[0-9a-zA-Z]*$/g;
	  	return reg.test(value);
	  },
	  

	  /**
	   * 验证一个值范围[min, max]
	   */
	   range(value, param) {
	  	return value >= param[0] && value <= param[1]
	  },
	  
	  /**
	   * 验证一个长度范围[min, max]
	   */
	   rangeLength(value, param) {
	  	return value.length >= param[0] && value.length <= param[1]
	  },
	  
	  /**
	   * 是否固定电话
	   */
	   landline(value) {
	  	var reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/;
	  	return reg.test(value);
	  },
 
  }  
 

 // -------正则 end------------------------------------------------------------------------------------- 
   
   
   
   
  
  //vue2 nextTick------------------------------------------------------------------
  // 定义一个队列
  const queue = [];
  
   function queueJob(job){
      // 不存在队列中,则放入 
       if(!queue.includes(job)){
           queue.push(job)
       }
       
       // 放入微队列中执行
      nextTick2(() => {
           let jobFn
           // 取出队列中的第一个effect进行执行
           while(jobFn = queue.shift()){
              jobFn && jobFn()
           }
      })
  }
  
   function nextTick2(fn){
    return fn ? Promise.reslove.then(fn) : Promise.reslove()
  }
  
  
  
  function nextTick (cb, ctx) {
      var _resolve;
        // 放入回调函数,等待DOM重新渲染完毕后执行
      callbacks.push(function () {
        if (cb) {
          try {
            // 修改执行上下文,指向当前页面实例
            // 所以在我们没有使用箭头函数的前提下,this指向仍然正确
            cb.call(ctx);
          } catch (e) {
            handleError(e, ctx, 'nextTick');
          }
        } else if (_resolve) {
          _resolve(ctx);
        }
      });
      if (!pending) {
        pending = true;
        timerFunc();
      }
      // $flow-disable-line
      if (!cb && typeof Promise !== 'undefined') {
        return new Promise(function (resolve) {
          _resolve = resolve;
        })
      }
      }
  	// 原型链上,挂载此方法
  	// Vue.prototype.$nextTick = function (fn) {
  	//       //参数1:回调函数,参数二:页面实例执行上下文
  	//       return nextTick(fn, this)
  	//     };
  	
  	
  	//timerFunc()
  	//Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,
  	//如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。
  
      //宏任务耗费的时间是大于微任务的,所以在浏览器支持的情况下,优先使用微任务。
  	//如果浏览器不支持微任务,使用宏任务;但是,各种宏任务之间也有效率的不同,需要根据浏览器的支持情况,使用不同的宏任务。
  	
  	//
  	const callbacks = []   // 回调队列
  	let pending = false    // 异步锁
  	
  	// 执行队列中的每一个回调
  	function flushCallbacks () {
  	  pending = false     // 重置异步锁
  	  // 防止出现nextTick中包含nextTick时出现问题,在执行回调函数队列前,提前复制备份并清空回调函数队列
  	  const copies = callbacks.slice(0)
  	  callbacks.length = 0
  	  // 执行回调函数队列
  	  for (let i = 0; i < copies.length; i++) {
  	    copies[i]()
  	  }
  	}
  
  
    let timerFunc;
    /* 优先检测微任务(micro task) */
    // 检测浏览器是否原生支持 Promise
    if (typeof Promise !== 'undefined') {
      const p = Promise.resolve()
      timerFunc = () => {
        p.then(flushCallbacks)
      }
      isUsingMicroTask = true
    } 
    // 以上都不支持的情况下,使用setTimeout
    else {
      timerFunc = () => {
        setTimeout(flushCallbacks, 0)
      }
    }
  
  
  
  //vue3 nextTick-------------------------------------------------------------------------
  const resolvedPromise =  Promise.resolve();
  let currentFlushPromise = null;
  function nextTick(fn) {
      const p = currentFlushPromise || resolvedPromise;
      return fn ? p.then(this ? fn.bind(this) : fn) : p;
  }
  // ————————————————
  // 版权声明:本文为CSDN博主「haruhiSzmy」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
  // 原文链接:https://blog.csdn.net/qq_42316310/article/details/125389053
  
  //------------------------------------------------------------------------------
   
   
   
   
   
   
   
   
   
   
   
   
  //https://github.com/view-design/ViewUIPlus/blob/master/src/utils/assist.js 
// download file
export async function downloadFile(url, name = 'unnamed') {
    if (!isClient) return Promise.reject();
    try {
        const res = await fetch(url);
        const blob = await res.blob();

        if (!blob) return Promise.reject();

        const localUrl = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.setAttribute('href', localUrl);
        a.setAttribute('download', name);
        a.click();
        URL.revokeObjectURL(localUrl);
        return Promise.resolve();
    } catch(e) {
        return Promise.reject(e);
    }
}

  

 省市区 正则

var reg = /.+?(省|市|自治区|自治州|县|区)/g;
	var addressList = address.match(reg).toString().split(",");
	this.address.cityName = addressList[1];	

  

table表格单元格的合并详解

/**
 * mergeCells 单元格合并处理
 * @param text 当前单元格的值
 * @param data 当前表格分页所有数据
 * @param key 当前列的dataIndex
 * @param index 当前数据所在下标
 * @param parentId 限定范围 []
 * @returns {number} 待合并单元格数量
 */
function mergeCells(text, data, key, index, parentId) {
  if (data.length < 1) {
    return 1;
  }
  if (text === '' || text === null) {
    data[index].rowNum = 1;
    return 1;
  }

  var spanArr = [];
  var pos = 0;

  for (var i = 0; i < data.length; i++) {
    if (i === 0) {
      spanArr.push(1);
      pos = 0;
    } else {

      if (parentId) {
        if (!Array.isArray(parentId)) {
          parentId = [parentId];
          //console.log("parentId", parentId)
        }
        var canNext = true;
        for (var s = 0; s < parentId.length; s++) {
          var propOne = parentId[s];
          if (data[i][propOne] !== data[i - 1][propOne]) {
            canNext = false;
            break;
          }
        }

        if (canNext && data[i][key] === data[i - 1][key]) {
          spanArr[pos] += 1;
          spanArr.push(0);
        } else {
          spanArr.push(1);
          pos = i;
        }

      } else {
        // 判断当前元素与上一个元素是否相同
        if (data[i][key] === data[i - 1][key]) {
          spanArr[pos] += 1;
          spanArr.push(0);
        } else {
          spanArr.push(1);
          pos = i;
        }
      }
    }
    // console.log("spanArr", spanArr);
  }
  return data[index].rowNum = spanArr[index];
};

 


elementui table 使用方式

 <el-table:data="treeMenu" :span-method="objectSpanMethod" >

 

  objectSpanMethod({
        row,
        column,
        rowIndex,
        columnIndex,
      }) {

if (columnIndex == 2) {
          var prop = 'amount1'
          var value = row.name;
          var index = rowIndex;
          var rowspan = mergeCells(value, this.treeMenu, prop, index, ["vid", 'name']) // 获取需要合并的行数
          // console.log(rowIndex, "name rows", rowspan)
          return {
            rowspan: rowspan ? rowspan : 0,
            colspan: rowspan ? 1 : 0
          };
        }


}

 

 

posted @ 2019-05-05 17:03  surfaces  阅读(376)  评论(0编辑  收藏  举报