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 除了添加let和const命令,
还有 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;
}
对象相等
function isEqual(x, y) {
function isObject(object) {
return object != null && typeof object === 'object';
}
if(isObject(x)&&isObject(y)){
rerturn JSON.stringify(x) === JSON.stringify(y)
}
if(x === y ){
//处理+0 和 -0的情况,应该返回false
return x!==0 || 1/x == 1/y;
}else{
//处理NaN的情况
return x!==x && y!==y;
}
}
移动端 键盘事件
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
};
}
}


浙公网安备 33010602011771号