壹 ❀ 引

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

 贰 ❀ 测试环节

题目一:

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. MySQL Error Log 文件丢失导致The server quit without updating PID file启动失败的场景

    今天在做mysql sniff测试的时候,中间重启MySQL实例的过程中,出现了"The server quit without updating PID file"这个经典的错误 ...

  2. mysql从5.6升级到5.7后出现 Expression #1 of ORDER BY clause is not in SELECT list,this is incompatible with DISTINCT

    [问题]mysql从5.6升级到5.7后出现:插入数据和修改数据时出错Caused by: com.ibatis.common.jdbc.exception.NestedSQLException: - ...

  3. mongodb使用_遍历列表中的元素,作为变量,循环修改mongodb中的字段

    一.问题描述: 需要将工作界面上的一些已经离职的用户状态改为失效,并备注为离职 二.需要准备/拿到手的工具/条件/数据: 1.已离职人员名单(excel格式) 2.任意mongodb工具(笔者使用的是 ...

  4. django重点url,视图函数,模板语言

    django重点url,视图函数,模板语言url 1.django重点url无命名分组:re_path() 2.url第一个参:url未命别名分组就不需要views中参数一定,若命别名(?P<y ...

  5. fiddler添加IP列

    willow一个规则管理插件 Ctrl+F查找“static function Main()”字符串,然后添加以下代码: FiddlerObject.UI.lvSessions.AddBoundCol ...

  6. 使用ping网络工具编写Shell脚本程序实现网络连接故障初步排查

    在学习ping命令的时候,突发奇想:为何不使用ping命令对网络连接故障进行排查? 具体思路: 1. ping  127.0.0.1 (虚拟网卡地址)以检查主机的TCP/IP协议栈是否正常. 2. p ...

  7. Vue.js学习笔记--菜鸟搭建一个企业级vue的项目

    vue.js新手搭建一个企业项目,从0开始 前置条件: node.npm请先安装配置好 下面开始: npm 下载vue-cli脚手架工具  确认安装成功看到版本号: 初始化项目,选用webpack(p ...

  8. Java入门系列之StringBuilder、StringBuffer(三)

    前言 上一节我们讲解了字符串的特性,除了字符串类外,还有两个我们也会经常用到的类,那就是StringBuffer和StringBuilder.因为字符串不可变,所以我们每次对字符串的修改比如通过连接c ...

  9. PlayJava Day021

    容器: Collection接口:定义了存取一组对象的方法,其子接口Set和List分别定义了存储方式 List:存储数据有序且可重复 ----> ArrayList Set:存储数据无序且不可 ...

  10. Python迭代器(函数名的应用,新版格式化输出)

    1. 函数名的运用 ​ 你们说一下,按照你们的理解,函数名是什么? ​ 函数名的定义和变量的定义几乎一致,在变量的角度,函数名其实就是一个变量,具有变量的功能:可以赋值:但是作为函数名他也有特殊的功能 ...