数组扁平化

js数组扁平化

// 数组扁平化
        const arr = [1,[2,[3,[4,5]]],6];
        //1:使用flat
        const arrflat = arr.flat(Infinity);
        console.log(arrflat);
        //2:使用正则
        const res2 = JSON.stringify(arr).replace(/\[|\]/g,'').split(',');
        console.log(res2);//数据会变成字符串
        //3:正则改良版本
        const res3 = JSON.parse('['+ JSON.stringify(arr).replace(/\[|\]/g,'')+']');
        console.log(res3);
        //4:使用reduce
        const flatten = arr => {
            return arr.reduce((pre,cur) => {
                console.log(pre);
                return pre.concat(Array.isArray(cur) ? flatten(cur) : cur);
            },[])
        }
        const res4 =  flatten(arr);
        console.log(res4);
        //函数递归
        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]);
                }
            }
            return res5;
        }
        console.log(fn(arr));

js数组去重

1:利用set
const arr = [1, 1, '1', 17, true, true, false, false, 'true', 'a', {}, {}];const res1 = Array.from(new Set(arr));
​   console.log(res1);
2:两层for循环加上splice

const res2 = arr => {let len = arr.length;for(let i =0;i < len;i++){for(let j = i + 1;j < len;j++){if(arr[i] === arr[j]){
​            arr.splice(j,1);
​            len--;
​            j--;}}}return arr;}
​    console.log(res2(arr));
3:利用indexof
 const res3 = arr => {const res = [];for(let i = 0;i < arr.length;i++){if(res.indexOf(arr[i]) === -1)res.push(arr[i]);}return res;}
​    console.log(res3(arr));
4:利用includes
 const res4 = arr => {const res = [];for(let i =0;i < arr.length;i++){if(!res.includes(arr[i]))res.push(arr[i])}return res;}
​    console.log(res4(arr));
5:利用filter

const res5 = arr => {return arr.filter((item,index) => {return arr.indexOf(item) === index;})}
​    console.log(res5(arr));
6:利用Map
 const res6 = 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(res6(arr));
const DEFAULTS = {
  logLevel: 0,
  outputFormat: 'html'
};

function processContent(options) {
  options = Object.assign({}, DEFAULTS, options);
  console.log(options);
  // ...
}

防抖节流

1、防抖

通过setTimeout的方式,在一定时间间隔内,将多次触发的事件一次触发。

btn.addEventListener('click',debounce(submit,2000),false);

function submit(e){// console.log(this);
​      console.log(1);}
function debounce(fn, timer){var t = null;return function(){var firstClick = !t;if(t){ clearTimeout(t); }
​        
​        if(firstClick){
​          fn.apply(this,arguments);}
​        console.log(t);
​        t = setTimeout(() => {
​          t = null;}, timer)}}

在第一次点击的时候触发,调用submit函数,在设置的时间间隔内再次点击按钮时,var t = null 是不会执行的,执行的是返回的那个函数,此时的 t 不是null,所以定时器就会被清除掉了,也不会调用submit函数了。

当时间间隔过去之后,t 的值已经被设置为了null,所以在时间间隔后再次点击按钮的时候,就不会清除定时器,就会调用submit函数,从而就实现了在多次点击之后只会执行一次事件调用了。

2、节流

就是在一段时间内减少事件的触发频率。

源代码如下:

var btn = document.getElementById("input");
btn.addEventListener('click', throttle(submit, 2000), false);

   function submit(e) {
​    console.log(e, this);
   }

   function throttle(fn,delay){var begin = 0;return function(){var cur = new Date().getTime();if(cur - begin > delay){
​        fn.apply(this,arguments);
​        begin = cur;
​        console.log(begin);}}
   }

第一次点击按钮的时候,记录下当时的时间(为1970年来的毫秒数),然后设置一个开始的时间 begin = 0,用记录的时间减去设置的开始时间,如果得到的差大于我们设置的时间间隔的话,就会去调用submit函数,也就是说在时间间隔以内连续点击按钮的话,是不会执行submit函数的,也就是说相应的两个时间的间隔就是比设置的时间间隔长了一点点而已,从而达到了节流的效果.

http和https

http为什么不安全:因为http通信的时候是采用的明文,没有加密,内容可能被窃听。也无法验证接收报文的完整性,可能已经被篡改了。并且http也不验证通信方的身份,因此有可能被伪装。

https:简单来说,https就是http+加密+证书+完整性保护构成的。

在数据传输阶段,使用对称加密,就是再加密和解密的时候使用的是同一个密钥,只要攻击者拿到密钥,就一样可以进行攻击。证书交验阶段,采用非对称加密技术。

https采用的是混合加密。

tcp和udp

tcp提供了一种可靠的、面向连接的、字节流、传输层的服务,采用三次握手建立一个连接,四次挥手来关闭一个连接。

三次握手原理:

1、客户端发送syn(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认。

2、服务器接收到syn,必须确认客户端的SYN(ack = x + 1),同时自己也发送一个SYN(syn = y),即SYN+ACK包,此时服务器进入SYN_RECV状态。

3、客户端接收到服务器端的SYN+ACK包,向服务器发送确认包ACK(ack = y+1),发送完毕,客户端和服务器端进入ESTABLISHED状态,完成三次握手。

为什么要三次握手?

保证客户端和服务器端的接收能力和发送能力都是正常的。

js的this指向

默认指向

默认指向全局对象window

 function a(){
     console.log(this);
 }
a();//Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}

隐式绑定:

var girl = {
    name: 'haha',
    detail: function(){
        console.log('姓名'+ this.name);
    }
}
girl.detail();//姓名haha

硬绑定

var girl = {
    name: 'haha',
    detail: function(){
        console.log('姓名'+ this.name);
    }
}
var girl1 = {
    name: '小白',
}
var girl2 = {
    name: '小红',
}
girl.detail.call(girl1);//姓名小白
girl.detail.call(girl2);//姓名小红
girl.detail.apply(girl1);//姓名小白
girl.detail.apply(girl2);//姓名小红

构造函数绑定

function Lover(name){
    this.name = name;
    this.sayName = function(){
        console.log("我的老婆是"+this.name);
    }
}
var name = 'cabbage';
var dilireba = new Lover('迪丽热巴');
dilireba.sayName();//我的老婆是迪丽热巴

面试题目:

var name = '小白';
function special(){
    console.log("name"+this.name);
}
var girl = {
    name: '小红',
    detail: function(){
        console.log('name'+this.name);
    },
    woman:{
        name: '小黄',
        detail: function(){
            console.log('name'+this.name);
        }
    },
    special: special,
}
girl.detail();//里面的this指向当前调用这个方法的对象
girl.woman.detail();//里面的this指向当前调用这个方法的对象
girl.special();//里面的this指向当前调用这个方法的对象,如果没有 则会往上寻找。
var name = "小红";
function a(){
    var name = "小白";
    console.log(this.name);
}
function d(i){
    return i();
}
var b = {
    name: "小黄",
    detail: function(){
        console.log(this.name);
    },
    bibi: function(){
        return function(){
            console.log(this.name);
        }
    },
}
var c = b.detail;
b.a = a;
var e = b.bibi();
a();
c();
b.a();
d(b.detail);
e();
//输出:
//小红
//小红
//小黄
//小红
//小红

JS变量和函数使用

map和parseInt的用法:

var arr = ['1','5','6'];
var a = arr.map(function(item,index,array){
    console.log(item,index,array);
});
console.log(a);

map后面接收一个函数,函数里面有三个参数,分别是数组的值,下标和数组本身。

map和parseInt结合在一起:

 var arr = ['1','5','6'];
 var a = arr.map(function(item,index,array){
 	return parseInt(item,index,array);
 });
 console.log(a);
//输出结果  
/*(3) [1, NaN, NaN]
0: 1
1: NaN
2: NaN
length: 3*/

parseInt函数接收两个参数,第一个参数是数值型,第二个参数是要转换的进制类型,范围是在2-36之间。

否则就会返回NaN

var const let的区别

const let变量是不能被重复定义的。但是let是可以被重新赋值的,const变量是不可以被重新赋值的,但是const的数组是可以被改变内容的。

var关键字会有变量提升,但是赋值是不会被提升的。

let是没有变量提升的。const一旦声明就必须有定义。

let和const可以形成块级作用域:

{
	let content = "haha";
	console.log(content);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7JaWmxQm-1606267689078)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201008131159594.png)]

js数组的高级用法

//map的高级用法
        // 参数:接收两个参数,一个是回调函数,另一个是回调函数的this值(可选)。回调函数接收三个参数,分别是当前值,当前索引和整个数组。
        // 返回:函数返回一个新创建的数组,数组中的每个元素都经过了回调函数的处理,结果不改变原数组。
        let nums = [1,2,3];
        let obj = {val: 5};
        let newNums = nums.map(function(item,index,array){
            return item + index + array[index] + this.val;
            // return item + index + array[index];
        },obj);
        console.log(newNums);
        //reduce的高级用法
        // 参数:接收两个参数,一个是回调函数,另一个是初始值(可选)。回调函数接收三个参数,分别是积累值、当前值和整个数组。
        // 返回:函数返回一个值,该值由数组中的元素通过回调函数进行处理后积累得到的最终值。
        // 注:若没传初始值,则会将数组中的第一个元素作为积累值,从数组的第二个元素开始进行函数调用
        let nums1 = [1,2,3];
        let newNums1 = nums1.reduce(function(preSum,curVal,array){
            return preSum + curVal;
        },2);
        console.log(newNums1);
        //filter的高级用法
        // 参数:接收一个函数参数。函数接收一个默认参数,就是数组正在遍历的当前元素,函数参数的返回值是一个布尔值,若返回true,则数组元素得到保留。
        // 返回:函数返回一个新创建的数组,数组元素为通过函数参数调用返回true的元素,此函数不会改变原数组。
        let oldnums = [1,2,3,4,5,6,7,8,9];
        let newnums = oldnums.filter(function(val){
            // console.log(val%2)
            return val % 2;
        });
        console.log(newnums);
        //sort的高级用法
        // 参数:接收一个用于比较的函数,比较函数默认接收两个参数,分别是代表比较的两个元素。
        // 返回:返回一个经过比较函数调用的数组,此函数会改变原数组。
        //注:若没有传入比较函数,则会将数字转换成字符串,然后根据字符的unicode值进行升序排序,也就是根据字符串的比较规则进行升序排序
        let nums2 = [2,3,1,1,2,1,0];
        //两个比较的元素分别为a, b
        nums2.sort(function(a,b){
            if(a > b) return 1;
            else if(a < b) return -1;
            else if(a == b) return 0;
        });
        console.log(nums2.reverse())
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue树状数组扁平化是一个操作,用于将树状数组(也称为B树或二叉搜索树)中的数据结构扁平化为线性数据结构。这个操作通常用于数据展示和性能优化。 在Vue树状数组扁平化过程中,需要遍历树状数组,并将每个节点转换为对应的线性数据结构元素。这通常可以通过递归实现。 下面是一个简单的Vue树状数组扁平化的实现步骤: 1. 定义一个数据结构来表示树状数组中的节点。每个节点包含一个数据值和指向其子节点的指针。 2. 定义一个递归函数,用于遍历树状数组并转换每个节点。该函数需要接受当前节点的值和指针,以及一个空列表(用于存储扁平化的结果)。 3. 在函数中,检查当前节点是否有子节点。如果有,递归调用函数自己处理子节点。否则,将当前节点的值添加到结果列表中。 4. 最后,遍历完成后,将结果列表转换为一个普通的数组或其他适当的线性数据结构,并将其传递给Vue组件进行展示。 需要注意的是,Vue树状数组扁平化操作可能会对性能产生一定的影响,特别是在处理大型数据集时。因此,在实现过程中需要考虑性能优化措施,例如使用分页或懒加载等技术来减少不必要的计算和渲染。 此外,为了更好地使用Vue树状数组扁平化,你可能需要使用Vue的数据绑定机制和组件系统来动态地呈现扁平化的数据结构。你可以创建一个组件来显示扁平化的数据,并使用Vue的数据绑定语法将其与数据源进行绑定。 总之,Vue树状数组扁平化是一个常用的操作,可以帮助你更有效地处理树状数组数据,并提高性能和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值