概述
javascript 操作 整理的乱七八糟
1.快速创建数据
let arr3 = new Array(5).fill(1).map((val,index)=>({name:('zhangsan'+index),age:(18+index)}));
[
{ name: "zhangsan0", age: 18 }
{ name: "zhangsan1", age: 19 }
{ name: "zhangsan2", age: 20 }
{ name: "zhangsan3", age: 21 }
{ name: "zhangsan4", age: 22 }
]
2.输出页面中所有使用过的标签种类有哪些,分别是什么?
var objs = Array.from(document.getElementsByTagName('*'));
var setArr = new Set(objs.map(val=>val.tagName));
console.log('有多少个标签: '+setArr.size);
var str = Array.from(setArr).join(',');
console.log('它们分别是: '+str);
3.将数组的每一项加+1,通过Array.from的第二个参数
var arr = [1,2,3,4];
var res = Array.from(arr,val=>val+1);
- 深拷贝、浅拷贝的区别与实现方式
-
基本类型与引用类型
基本类型:字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
引用类型:对象(Object)、数组(Array)、函数(Function)
基本类型存在栈内是一个具体的值
引用类型存在栈内是一个内存地址,通过这个地址找过去是一个堆(方便扩展,内存分配大小未知) -
深拷贝与浅拷贝的区别:
由于javascript数据类型,有两种,一个是基本类型,一个是引用类型
针对基本类型的拷贝是 深拷贝 (操作的数据,真实数据在内存的栈里)
针对引用类型的拷贝是 浅拷贝 (操作的数据,真实数据在堆里,栈里只保存一个堆的地址) -
浅拷贝的实现:
数组浅拷贝 方法1
var a1 = [12,{'a':1},47,56,213,4654,154];
var a2 = Array.from(a1);
a2[1].a = 2;
console.log(a1[1].a); //2
数组浅拷贝 方法2
var a1 = [12,{'a':1},47,56,213,4654,154];
var a2 = a1.slice(0);
a2[1].a = 2;
console.log(a1[1].a); //2
- 深拷贝的实现:
方式一:ES6新语法
JSON.parse(JSON.stringify(obj))
但是需要注意问题 ,数据中嵌套的值不能含有( new Date、RegExp、Error、函数,undefined、NaN、Infinity和-Infinity、实例 )
方式二:遍历方式
//commonTools.deepClone(obj)
let commonTools=(function(){
function isArray(val) {
return Object.prototype.toString.call(val) === '[object Array]';
}
function isObject(val) {
return typeof val === 'object' && val !== null;
}
function doit(obj2) {
var obj = isArray(obj2) ? [] : {};
for (var property in obj2) {
if (isObject(obj2[property])) {
obj[property] = doit(obj2[property]);
} else {
obj[property] = obj2[property];
}
}
return obj;
}
return {
deepClone : doit
}
})();
- 判断原型
Object.prototype.toString.call(new Date()); //"[object Date]"
Object.prototype.toString.call([1,2,34]); //"[object Array]"
5-2. 调用不同类型特有的方法
如: 类数组 => 数组
var 新数组 = Array.prototype.slice.call(类数组);
- 简单防止copy,但是通过浏览器菜单内开发者工具,是可以跳过去的
document.onkeydown=function(){
var e = window.event||arguments[0];
if(e.keyCode==123){
alert('请尊重劳动成果');
return false;
}else if((e.ctrlKey)&&(e.shiftKey)&&(e.keyCode==73)){
alert('请尊重劳动成果!');
return false;
}else if((e.ctrlKey)&&(e.keyCode==85)){
alert('请尊重劳动成果!');
return false;
}else if((e.ctrlKey)&&(e.keyCode==83)){
alert('请尊重劳动成果!');
return false;
}
}
document.oncontextmenu=function(){
alert('请尊重劳动成果!');
return false;
}
- 一些简写
- 浅拷贝
var newArr = arr1.slice(0);
- 16位随机数
var num = 15;
var a = num.toString(); //--10进制
var b = num.toString(2); //--2进制
var c = num.toString(8); //--8进制
var d = num.toString(16); //--16进制
Math.random().toString().substring(2, 15);
- 获取object的key MDN链接
支持ES6的
var keys= Object.keys(obj);
var values = Object.keys(obj).map(key => row[key]);
var values= Object.values(obj);
不支持ES6、兼容性( IE9-10 )
var obj = { 0: "a", 1: "b", 2: "c"};
console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]
- 判断空对象 法1
JSON.stringify(object) == {}
- 判断空对象 法2
function checkObj(obj) {
for(var key in obj) {
return false;
}
return true;
}
- 微信自动播放的生命周期(考古)
<audio controls="controls">
<source src="music/bg.ogg" type="audio/ogg"></source>
<source src="music/bg.mp3" type="audio/mpeg"></source>
优先播放音乐bg.ogg,不支持在播放bg.mp3
</audio>
javascript
//微信下兼容处理
document.addEventListener("WeixinJSBridgeReady", function () {
music.play();
}, false);
- stopPropagation针对主流浏览器,cancelBubble针对IE浏览器(现在也可以作用主流浏览器)
_btn1.onclick = function(ev){
var oEv = ev || window.event;
stopBubble(oEv);
console.log(111);
};
//stopBubble
function stopBubble(oEv){
if(oEv.stopPropagation){
oEv.stopPropagation();
}else{
oEv.cancelBubble= true;
};
}
第10条的修改 getPropertyPriority ----- 待完成!!!!!!!!!!!!!!!!!!
- 判断是否支持某些CSS属性
判断支持css3某些属性
function supportCss3(style){
var prefix = ['webkit','Moz','ms','o'],i,humpString = [],htmlStyle = document.documentElement.style,_toHumb = function(string){
return string.replace(/-(\w)/g,function ($0,$1){
return $1.toUpperCase();
});};
for(i in prefix)
humpString.push(_toHumb(prefix[i] + '-' + style));
humpString.push(_toHumb(style));
for (i in humpString)
if (humpString[i] in htmlStyle) return true;
return false;
}
- 设置css3
function css3(obj, attr, val) {
var str = attr.charAt(0).toUpperCase() + attr.substring(1);
obj.style['Webkit' + str] = val;
obj.style['Moz' + str] = val;
obj.style['ms' + str] = val;
obj.style['O' + str] = val;
obj.style[attr] = val;
}
//使用
css3(somedom, 'transform', 'scale(' + _tc + ')');
- 浏览器是否支持某标签
如:音频audio标签
!!document.createElement('video').play;
'play' in document.createElement('video');
- 判断两个点的夹角与距离
//判断两个点夹角
function getAngle(p1, p2) {
var x = p1.pageX - p2.pageX,
y = p1.pageY - p2.pageY;
return Math.atan2(y, x) * 180 / Math.PI;
};
//两点距离
function getDistance(p1, p2) {
var x = p2.pageX - p1.pageX,
y = p2.pageY - p1.pageY;
return Math.sqrt((x * x) + (y * y));
}
- 获取一个范围的随机值
function randomRange(myMin, myMax) {
return Math.floor(Math.random()*(myMax - myMin+1)) + myMin;
}
- 一个元素的抖动
function shake(obj, attr, endFn) {
var arr = [];
var timer = null;
var n = 0;
if (!obj.num) {
obj.num = parseFloat(getComputedStyle(obj)[attr]);
}
//拿到一组数字,抖动的幅度。
for (var i = 20; i > 0; i -= 2) {
arr.push(i, -i);
}
arr.push(0);
//用定时器来实现抖动效果。
clearInterval(timer);
timer = setInterval(function () {
n++;
if (n > arr.length - 1) {
clearInterval(timer);
endFn && endFn();
}
obj.style[attr] = arr[n] + obj.num + 'px';
}, 30);
}
- 判断是否为一个数字 ( isFinite兼容IE4+,判断是否为一个有限数字)
function isNumber(n){
return !isNaN(parseFloat(n)) && isFinite(n);
}
- 数组最大值最小值,传递一个数组 (Math.max兼容IE3+)
var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
var maxInNumbers = Math.max.apply(Math, numbers);
var minInNumbers = Math.min.apply(Math, numbers);
-
宏任务、微任务
事件执行顺序
执行顺序, 同步任务 > 微任务 > 宏任务
同步任务: promise的逻辑部分
宏任务: setTimeout、setInterval
微任务: promise的then -
箭头函数与普通函数的区别
a. 二者的书写方式( 缩写方式也 )不用,箭头函数表现的更加简洁
b. 箭头函数中的this,为其上下文中的this,或者说箭头函数没有自己的this
c. 箭头函数不能作为构造函数使用,不能使用new,( 因为函数没有自己的this )
d. 箭头函数没有自己的arguments ( arguments实际上获得的是外层局部(函数)执行环境中的值 )
e. call、apply、bind 并不会影响其 this 的指向
f. 箭头函数没有原型prototype、箭头函数不能当作 Generator 函数,不能使用 yield 关键字
数据类型 相关
- 基本数据类型和引用数据类型的区别
- 基本数据类型不可以添加属性和方法、引用类型可以添加属性和方法
- 基本数据类型的赋值是简单赋值、引用类型的赋值是对象引用(即声明的变量标识符,存储的只是对象的指针地址)
- 基本数据类型是存放在栈区的、引用类型在栈里存的是一个内存地址,所在地址的内容在堆中( 引用类型是同时保存在栈区和堆区中的,栈区保存变量标识符和指向堆内存的地址 )
- 基本数据类型的比较是值的比较、引用类型的比较是引用(指针地址)的比较
promise相关
- async await 是怎么解析的
async await是一个语法糖,
async理解为函数返回一个promise,
await理解为后面函数.then
例如:
async function fn1(){
let data1 = await ajaxFn('xxx');
console.log(1);
return 100;
}
- await 删除await,await后面的代码都放在一个then的处理函数中,await之前接收的变量放在then的参数中
会被解析为
async function fn1(){
ajaxFn('xxx').then(data1=>{
console.log(1);
return 100;
});
}
- async会被解析为一个新的Promise
function fn1(){
return new Promise((reslove,reject)=>{
ajaxFn('xxx').then(data1=>{
console.log(1);
reslove(100);
});
});
- async await对比promise的优缺点
-
async/await优点:
a. 它做到了真正的串行的同步写法,代码阅读相对容易
b. 对于条件语句和其他流程语句比较友好,可以直接写到判断条件里面
c. 处理复杂流程时,在代码清晰度方面有优势 -
async/await缺点:
a. 无法处理promise返回的reject对象,要借助try...catch...
b. 用 await 可能会导致性能问题,因为 await 会阻塞代码,也许之后的异步代码并不依赖于前者,但仍然需要等待前者完成,代码失去了并发性
c. try...catch...内部的变量无法传递给下一个try...catch...,只能在外层作用域先定义好。 -
promise的一些问题:
a. 一旦执行,无法中途取消,链式调用多个then中间不能随便跳出来
b. 错误无法在外部被捕捉到,只能在内部进行预判处理,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
c. Promise内部如何执行,监测起来很难,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
数组扁平化
- ES6语法
arr.flat(Infinity);
- 通过正则删除数组前后符号'['与']'
JSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g, '') + ']');
- Array.isArray() 与 Array.prototype.reduce 兼容均为IE9+
const flatten = arr => {
return arr.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? flatten(cur) : cur);
}, [])
}
const res4 = flatten(arr);
- 函数递归
const res5 = [];
const fn = arr => {
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
fn(arr[i]);
} else {
res5.push(arr[i]);
}
}
}
fn(arr);
数组去重
- 利用ES6 Set特性
const res1 = Array.from(new Set(arr));
- 遍历数组去重
res.indexOf(arr[i]) === -1
同!res.includes(arr[i])
const unique2 = arr => {
const res = [];
for (let i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) === -1) res.push(arr[i]);
}
return res;
}
- 通过Map来做去重标记
var arr = [1, 2, 1, 5, 6, 5];
const unique5 = arr => {
const map = new Map();
const res = [];
for (let i = 0; i < arr.length; i++) {
if (!map.has(arr[i])) {
map.set(arr[i], true)
res.push(arr[i]);
}
}
return res;
};
console.log(unique5(arr));
数组常用方法
-
map()
return 是针对item的处理
map() 数组方法的行为就像一个纯函数,不会改变原始数组 -
filter()
return 是一个条件,返回符合条件的item
filter() 函数行为就像一个纯函数,不会改变原始数组 -
find()
return 是一个条件,返回符合条件的item
find() 数组方法用于在数组中查找给定对象 -
forEach()
遍历数组 -
some()
return 一个条件,某一个遍历项符合条件,就返回true
some函数行为就像一个纯函数,不会改变原始数组 -
every()
return 一个条件,每一个遍历项都符合条件,才返回true
every函数行为就像一个纯函数,不会改变原始数组 -
reduce()
遍历数组
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
total - 必需。初始值, 或者计算结束后的返回值。
currentValue - 必需。当前元素
currentIndex - 可选。当前元素的索引
arr - 可选。当前元素所属的数组对象。
initialValue - 可选。传递给函数的初始值 -
includes() (兼容IE14+)
数组内是否包含某项(第二个参数可选,某个索引位置)
arr.includes(searchElement, fromIndex)
防抖与节流
- 触发高频时间后n秒内函数只会执行一次,如果n秒内高频时间再次触发,则重新计算时间。
应用场景: 类似百度框的搜索输入
const debounce = (fn, time) => {
let timeout = null;
return function() {
clearTimeout(timeout)
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, time);
}
};
- 高频时间触发,但n秒内只会执行一次,所以节流会稀释函数的执行频率。
const throttle = (fn, time) => {
let flag = true;
return function() {
if (!flag) return;
flag = false;
setTimeout(() => {
fn.apply(this, arguments);
flag = true;
}, time);
}
}
未完待续....
网友评论