记录前端路上每天的成长。(持续更新)

记录前端路上每天的成长(持续更新)

2020.12.13 关于数组去重引发的思考

数组去重,在网上可以找到好多方法,最少得有11种方法,而面试的时候,主考官最想看见的回答还是关于使用hasOwnProperty的去重方法。
具体的去重代码如下:
  function unique(arr) {
        var obj = {};
        return arr.filter(function(item, index, arr) {
            return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)

        })
    }
    var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
    console.log(unique(arr));

其中,有一个让人比较困惑的点,就是关于(typeof item + item),经过自己测试之后发现,它会先进行typeof item这个运算,然后typeof item的值再加上item。
就好比如下代码:

 var item = 1;
    console.log(typeof item + item);  //number1
    var item = false;
    console.log(typeof item + item);  //booleanfalse
    var item = 'false';
    console.log(typeof item + item);  //stringfalse
    var item = null;
    console.log(typeof item + item);  //objectnull
    var item = {};
    console.log(typeof item + item);  //object[object Object]
    var item = [];
    console.log(typeof item + item);  //object

这前几个例子不难理解,难理解的是后面两个,为什么当item是空数组或者空对象的时候,返回的结果好像不太一样。
其实这个也比较好解释,这两个例子还是遵循之前的规则,先进行typeof item所以返回的是object。然后在进行+ item这个操作。
而这个+号,会进行隐式转换,它会向字符串这个方向转换,而 - *这个符号会向数字这个方向转换。所以空数组转化成字符串是’ ',空对象转换成字符串是[object Object]。

2020.12.15 开始尝试简单的手写代码实现一些简单功能(面试常考的)

就先从最简单的Ajax开始吧
let xhr;
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    } else{
        xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xhr.onreadystatechange = function() {
        if(xhr.readyState === 4){
            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
                let mes = JSON.parse(xhr.responseText);
                console.log(mes);

            }
        }
    }
    xhr.open('get', "url", true);  //open中的第三个参数决定是否异步发送请求。true表示异步。
    xhr.send(null);

    //如果发送的是post请求,则在send里面发送数据,还要再加一行代码
    // xhr.setRequestHeader("Content-Type", "application/json");  这个要在调用open之后,调用send之前调用

这里面还有一个要注意的点就是xhr的readyState属性它有五个状态,分别是:
0:未初始化。尚未调用open()方法。
1:启动。已经调用open()方法,但尚未调用send()方法。
2:发送。已经调用send()方法,但尚未收到响应。
3:接收。已经接收到部分响应数据。
4:完成。已经接收到全部的响应数据,而且已经可以在客户端使用。

实现防抖和节流
防抖

防抖的定义:防抖是指在一定的时间内再次触发此事件,会清空上次的事件重新开始,如果制定的时间内没有再次触发,那么这个事件才会执行。

例如: input输入信息,不可能每次按下都发起一个ajax请求,可以等一段时间内不输入了之后在发起请求。
代码如下:

function debounce(fn, delay){
	let timer = null;
	return function(){
		if(timer){
			clearTimeout(timer);	
		}
		timer = setTimeout(fn, delay);
	}
}

然后我们在给事件绑定函数的时候就可以使用这个函数,当然这里只是核心思想,没有考虑作用域等问题。

节流

定义:节流是指在一定的时间同一事件只会触发一次,只有超过了这个时间才会再次出发

例如: 验证码60秒内不可以再次触发(实际开发肯定是使用禁止,但是原理和验证码一样)
代码如下:

function(fn, delay){
	let flag = true;
	return function(){
		if(!flag) return;
		flag = false;
		setTimeout(() => {
			fn();
			flag = true;	
		},delay);
	}	
}

2020.12.21数组或对象的深浅拷贝

浅拷贝
浅拷贝与深拷贝的主要区别在于浅拷贝在拷贝引用类型的值的时候,只会复制它的地址,也就是说拷贝之后两者共用一个地址,只要其中一个引用类型的值发送变化的时候,另一个也会受到影响,而这往往不是我们希望看到的。具体代码如下(此处只展示一种拷贝方法):

        let obj = {
            a: 100,
            b:[10,20,30],
            c: {
                x: 10
            },
            d: /^\d+$/
        };

        let obj2 = {};
        for(let key in obj) {
            if(!obj.hasOwnProperty(key)) break; //不是私有属性,不遍历
            obj2[key] = obj[key];
        }
        console.log(obj, obj2);

控制台输出的结果如下:
这个就是浅拷贝的结果
如果当我们改变obj2里面的引用值的数据时,obj也会跟着变化,如下图:

我们改变了obj2.c.x的值,结果obj里面对应的值也发生了改变。
当然了,要想避免这个情况发生,那我们可以使用深拷贝。

深拷贝

深拷贝相对于浅拷贝来说要复杂一些,但是也有一种比较简单的方法,就是使用JSON。代码如下:

 let obj = {
            a: 100,
            b:[10,20,30],
            c: {
                x: 10
            },
            d: /^\d+$/
        };

        let obj2 = JSON.parse(JSON.stringify(obj));

哈哈哈,是的,这种方法只需要一行代码,但是它也有自己的限制,那就是对函数,Symbol, undefined, 正则, Data对象等这些不能准确拷贝,但是平时开发中很少出现这种情况,所以开发中我们可以使用这种方法,但是这种方法不是面试官想听到的,所以我们还有一种比较好的方法:

function deepClone(obj){
            //过滤特殊情况
            if(obj === null) return null;
            if(typeof obj !== "object") return obj;
            if(obj instanceof RegExp) {
                return new RegExp(obj);
            }
            if(obj instanceof Date) {
                return new Data(obj);
            }
           //不直接创建空对象目的,克隆的结果和之前保持相同的所属类
           let newObj = new obj.constructor;
           for(let key in obj){
               if(obj.hasOwnProperty(key)){
                   newObj[key] = deepClone(obj[key]);
               }
           }
           return newObj;
       }
       let obj2 = deepClone(obj);
        console.log(obj, obj2);

这个代码只是深拷贝的部分代码,因为它还没有考虑function这个特殊情况,这个大家可以自己下去实现,也就是一个if判断语句,最后总结一下,js的深拷贝需要考虑一下四个点:
1、JSON 克隆不支持函数、引用、undefined、Date、RegExp 等
2、递归克隆要考虑环、爆栈
3、要考虑 Date、RegExp、Function 等特殊对象的克隆方式
4、要不要克隆 proto,如果要克隆,就非常浪费内存;如果不克隆,就不是深克隆。
真正意义上的深克隆实现起来弊大于利。

2021.3.6 关于js语言中为什么基本类型null的typeof为Object

之前学期末了,在复习考试,完了又再学vue写项目,一直没有更新,今天突然想起来了,就更新一个小知识,但是大多数人不知道东西。
我们都知道,js中null是基本类型,可是为什么typeof null的时候返回的结果是object呐?这其实跟js的底层逻辑有关,在js底层,会把每种类型用二进制数表示,而二进制数前三位为0的话就是object,但是null的二进制数全为0,所以typeof null也为object,这算是一个小bug吧。哈哈哈
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值