壹 ❀ 引

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

 贰 ❀ 测试环节

题目一:

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打脸,如果代码量大,还得花费较大的时间确认问题出自于哪里,这也是我被折磨后非常想要写一篇文章记录的原因。

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

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

js 记录几个因惯性思维引发的代码BUG,开发思维方式的自我反省的更多相关文章

  1. js记录用户在网站的浏览记录和停留时间

    by weber开发者 from http://weber.pub/ 本文地址: http://weber.pub/js记录用户行为浏览记录和停留时间/163.html 问题 公司想统计一个用户从进入 ...

  2. js记录用户行为浏览记录和停留时间(转)

    演示地址:http://weber.pub/demo/160902/test.html 测试源码下载:http://pan.baidu.com/s/1nvPKbSP 密码:r147 解决问题所使用的知 ...

  3. 打破惯性思维:聊聊一次debug

    最近公司的新需求中要增加活动营销,整个组的人都被安排去研究某成熟产品的实现.我也认真地在看webService部分的实现,发现了一个诡异的10614端口的请求. 代码如下图: 这是一段服务端发请求验证 ...

  4. Cocoa惯性思维调试一例

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 人总有惯性思维,在编程调试里也不例外.你总以为错误是显然的那一 ...

  5. 为什么我没有拔出钥匙 ——开锁引发的程序bug解决方案的思考

    http://blog.csdn.net/wojiushiwo987/article/details/8851204为什么我没有拔出钥匙                             ——开 ...

  6. js让菜单栏一直悬浮在顶部,经典代码

    js让菜单栏一直悬浮在顶部,经典代码 很简单,你只需要把下面代码放到js中:$(function(){                //获取要定位元素距离浏览器顶部的距离        var na ...

  7. JS年月日三级联动下拉框日期选择代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)_javascript技巧_

    JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)_javascript技巧_--HTML5中文学习网 http://www.html5cn.com.cn/shili/javascripts/79 ...

  9. m_Orchestrate learning system---三十五、php数据和js数据的解耦:php数据(php代码)不要放到js代码中

    m_Orchestrate learning system---三十五.php数据和js数据的解耦:php数据(php代码)不要放到js代码中 一.总结 一句话总结:也就是以html为中介,用html ...

随机推荐

  1. 学习Linux必看的命令(一)

    学习Linux必看的命令(一) 一:什么是Linux ​ Linux命令是对Linux系统进行管理的命令.对于Linux系统来说,无论是中央处理器.内存.磁盘驱动器.键盘.鼠标,还是用户等都是文件,L ...

  2. Tornado—添加请求头允许跨域请求访问

    跨域请求访问 如果是前后端分离,那就肯定会遇到cros跨域请求难题,可以设置一个BaseHandler,然后继承即可. class BaseHandler(tornado.web.RequestHan ...

  3. unittest---unittest简单介绍

    说起python的单元测试,第一反应肯定就会是unittest,unittest作为python的标准库,很优秀,也被广泛的用到各个项目,但是你们知道吗?python的单元测试并不只有这一个,还有个p ...

  4. VSCode+C++环境搭建

    date: 2019-10-05 VSCode+C++环境搭建 其实并不完整,毕竟我也只是一个OIer,并不会很高深的东西.(众所周知,OIer主业是软件开发) 安装VSCode 下载安装包 这个很简 ...

  5. Python selenium登录163邮箱示例

    思路:使用python自带的unittest单元测试框架测试163邮箱登录成功的case import unittestfrom selenium import webdriverimport tim ...

  6. 给定数轴上的n个点,求距离最近的两个点的距离

    public class MinimumSpacing { //给定平面上的n个点,求距离最近的两个点的距离. //无从下手的话,先分解问题,分解成简单的,逐个分析,然后再合在一起考虑 //这是个2维 ...

  7. 31.Java基础_日期/日期格式/日历类

    Date类 Date对象构造方法 Date对象常用方法 import java.util.*; public class test { public static void main(String[] ...

  8. spanish-1.1

    1.1. ¿Cómo te llamas?Ana : ¿Cómo te llamas?Paco: Buenos dias. Yo soy Paco. Y tú, ¿cómo te llemas?Ana ...

  9. 推荐系统| ② 离线推荐&基于隐语义模型的协同过滤推荐

    一.离线推荐服务 离线推荐服务是综合用户所有的历史数据,利用设定的离线统计算法和离线推荐算法周期性的进行结果统计与保存,计算的结果在一定时间周期内是固定不变的,变更的频率取决于算法调度的频率. 离线推 ...

  10. C++利用宏实现变量交换的三种方式

    #include <iostream> using namespace std; //引入中间变量 #define SWAP1(a,b) {int tmp=a;a=b;b=tmp;} // ...