• js 记录几个因惯性思维引发的代码BUG,开发思维方式的自我反省


     壹 ❀ 引

    在写这篇文章之前,对于取什么标题其实让我纠结了好几天,这篇文章中我想说的东西与引用类型数据有关,也与我们的惯性思维有关。本文中展示的几段代码都非常简单,原型都来自于我的日常开发,但让你立刻回答出正确答案可能还需要一点时间,不妨一起来看看吧。

     贰 ❀ 测试环节

    题目一:

    let getName = (name) => {
        return name;
    };
    let person = {
        name: getName('听风是风')
    };
    getName('echo');
    console.log(person);//?

    开发中初始化工作总是必不可少的,初始化数据,变量都是非常常见的操作。现在我需要初始化一个对象,而这个对象的值是一个被调用函数;于是在后面的程序中我需要更新这个对象,顺手再次调用了这个函数,那么请问此时这个对象能被更新吗?

    答案是并不会更新,其实仔细想想这怎么可能被会更新呢。但在开发中,因为引用类型数据保存是存放value的指针,这让我有了一种函数被再次调用return的值被刷新,于是person对象也被更新的错觉,听着挺蠢,可是我不严谨的惯性思维却真的写出了这样的代码,并调试了好一会BUG。

    题目二:

    let arr = [{
        id: 1,
        name: '听风是风'
    }, {
        id: 2,
        name: '时间跳跃'
    }];
    arr.forEach((item) => {
        item.a === 1 ? item = {id: 3,name: 'echo'} : null;
    });
    console.log(arr);//?

    日常开发中遍历数据的操作简直与我们每天要吃饭一样平常,那么现在我需要将数组中符合条件项的元素直接替换成另一个元素,也就是上述代码,请问执行完毕数组有被成功更改吗?

    答案是并没有更改,但惯性思维会让我觉得,此时的item就是数组中的某个对象,我将对象替换数组也会得到替换,这是潜意识的思维方式。

    但事实上item并不是数组中的某个元素,而是作为forEach回调函数的一个局部形参临时存储了数组中的某个元素,为了方便理解我们修改代码:

    arr.forEach((item,index) => {
        item = arr[index];//这一步是隐性的
        item.a === 1 ? item = {id: 3,name: 'echo'} : null;
    });

    上述代码再简化就是下面这段代码:

    let a = [1, 2];
    let b = a;
    b = [1, 2, 3];
    console.log(a); //[1,2]

    虽然变量b曾与变量a共享过数组[1,2]的地址指针,可是后来变量b变心了,改成保存数组[1,2,3]的指针,所以怎么可能会影响到变量a呢。上述例子也是,item被重新赋值关我数组何事,所以数组肯定不会被改变。

    但如果变量b不是做重新赋值,而是单纯的修改,这就会影响到变量a,因为它两其实保存的是同一个数组的指针,像这样:

    let a = [1, 2];
    let b = a;
    b[0] = 2;
    console.log(a); //[2,2]

    题目三:

    function fn(param) {
        param = 2;
    };
    let obj = {
        a: {
            b: 1
        }
    };
    fn(obj.a.b);
    console.log(obj);//?

    我有一个对象obj,它的属性层级有点高,在某个场景下我需要将此对象作为参数传入函数fn,达到赋值的操作,那么请问上述代码中的对象obj成功被赋值了吗?

    答案是并没有,让我产生可行错觉的原因是因为我觉得obj层级过高,为了统一和简化函数fn的赋值代码,我得清楚知道是给对象的哪一级赋值,于是才诞生了这样的写法。

    但只要稍微仔细一想,obj.a.b拿到的是一个具体的value,事实上我们只能给key赋值,哪里有给value赋值value的操作呢。

     叁 ❀ 总

    文章到这里,我一共展示了三个我个人觉得有趣也常让人误解的代码问题,这些问题稍加思考就会觉得特别简单,但事实上我将它们整理出来用于测试我的同事,他们居然都会犹豫,而且大部分都回答错误了。

    难的不是问题,难的是我们太容易相信自己的潜意识,惯性思维。它应该是这样,它应该会这么运行,但代码一跑总是被BUG打脸,如果代码量大,还得花费较大的时间确认问题出自于哪里,这也是我被折磨后非常想要写一篇文章记录的原因。

    在开发中明确一个变量一段执行此时是什么,而不是我觉得它应该是什么,写代码如果靠猜,往往在写完后会付出更多的时间用于调试,因为自己其实是不确定的,一个程序代码量越大,这种不确认感就会越强,反过来想不如确信后写更值得相信的代码要来的省时省力。

    这是一篇偏向自我反应的文章,不知道上述问题大家有没有遇见过,那么到这里本文结束。

  • 相关阅读:
    sql中where和having的区别
    mysql中locate和substring函数使用
    使用jdk进行数据迁移(sqlite迁移mysql)
    mysql数值函数
    mysql字符串函数
    zabbix-2.2.2(Ubuntu 14.04 LTS/OpenLogic 7.2)
    Piwik-2.16.1 (OpenLogic CentOS7.2)
    Nagios-4.1.1 (OpenLogic CentOS 7.2)
    Bugzilla-5.0.3 (OpenLogic CentOS 7.2)
    GitLab-CE-8.9.4 (OpenLogic CentOS 7.2)
  • 原文地址:https://www.cnblogs.com/echolun/p/11598545.html
Copyright © 2020-2023  润新知