记录日常的一个小bug,吃一堑长一智,今天要讲的就是 操作数组赋值指针指向问题。
事情原尾是这样的,调用查询测评接口返回一个resultList接口,测评页展示遍历走resultList;但由于条件筛选框的诞生,要根据学生name 作为条件传参,就得单独一栏只下拉展示学生名称,于是乎调用学生列表接口获取studentList,既然studentList值只返回学生name,但实际情况,是不是得给studentList 第0位给新加一个元素进去,有一个能选 ‘全部’,即不按name作为条件筛选 ,这样才显示合理,对吧;如下图。
先给你们看段代码,假如走如下逻辑,修改studentList2的值会不会同时改变studentList1的值???
//获取学生列表
getStudentList: function() {
var that = this;
var list = new Array();
var teacherId = wx.getStorageSync('userId');
wx.request({
url: that.data.host + '/student/listByTeacherId?teacherId=' + teacherId,
method: 'get',
success: function(e) {
list = e.data.result.list;
var studentListAdd= list ;
var stuObj = {
nickName: '全部',
userId: ''
}
studentListAdd.unshift(stuObj); // 筛选姓名列表 开头添加一个元素
that.setData({
studentList1: list,
studentList2: studentListAdd,
})
}
})
},
下面我再举个很简洁的栗子,注意看!
var a = [1, 2, 3]; //数组
var b = a;
b.unshift('aaa'); //开头添加一个元素
console.log("b=", b)
console.log("a=", a)
结果很让人出乎意料,随着我给b数组新增一个元素,结果也改变了a数组的值,同时都在数组的第0位加上了‘ aaa’元素;
于是很纳闷,结果问题就出在值引用,因为JavaScript存储对象都是存地址的(在js里数组不是简单数据类型,而是对象),所以浅复制会导致 a 和 b 指向同一块内存地址;变量是值传递,而数组是引用传递;
思路还是数组拷贝,但不能再是浅拷贝,那该如何深拷贝呢?请看下文
原理:返回数组的一个副本(相当于另外开辟内存空间),所以并不会改变数组本身的的值;
var a = [1, 2, 3]; //数组
var b = [].concat(a)
b.unshift('aaa'); //开头添加一个元素
console.log("b=", b)
console.log("a=", a)
再看打印结果,你发现了什么,竟然成功了,是不是感到很意外,想知道为什么要利用一个空数组去 拼接a 数组呢?
原因就是:
concat()返回的不是调用函数的Array,而是一个新的Array,开辟了一个新内存地址,同时也把a数组的元素复制给了b数组,所以第一次var b = a; 其实只把引用地址交给了b.所以两个数组 共享同一个 [ 1,2,3 ]数组对象,而当修改了数组b的时候,那么他们共享的内容就发生了变化,导致数组a输出的时候也发生了变化,变成了【‘a’,1,2,3】;
这样就完成了数组的拷贝,而不再是引用;即便无论怎么改变拷贝后的数组b,也不会影响原来的数组a!
给大家画个图辅助性理解下:
原理:返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。
var a = [1, 2, 3]; //数组
var b = [];
b=a.slice(0)//如果 end 未被规定,那么 slice() 方法会选取从 start 到数组结尾的所有元素
b.unshift('aaa'); //开头添加一个元素
console.log("b=", b)
console.log("a=", a)
结合实例理解,小伙伴们,你们都学废了吗?学废了的,记得给宝宝点个赞就当交学费啦!没学废了,建议反复观看,直到学废为止,反正这你们必须给我掌握[傲娇脸]┗( ´・∧・`)┛
最后,我就出道题考考大家,验收下大家是否有真正学会;
请听题:
var a = [1,2,3]; var b = a; a.pop(); //pop()方法 :删除数组对象的最后一个元素 这里是直接改变的数组对象[1,2,3] console.log("b=",b); //结果b=?
请问,输入数组b 为多少?
请大家留言栏见!我倒要看看,有多少小伙伴能回答上来,第一时间回答正确的小伙伴,我打算给予适当奖励哦!
定义和用法:
concat() 方法用于连接两个或多个数组。
该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
语法:
arrayObject.concat(arrayX,arrayX,......,arrayX)
参数 | 描述 |
---|---|
arrayX | 必需。该参数可以是具体的值,也可以是数组对象。可以是任意多个。 |
返回值:
返回一个新的数组。该数组是通过把所有 arrayX 参数添加到 arrayObject 中生成的。如果要进行 concat() 操作的参数是数组,那么添加的是数组中的元素,而不是数组。
详情请戳:https://www.w3school.com.cn/jsref/jsref_concat_array.asp
定义和用法:
slice() 方法可从已有的数组中返回选定的元素。
语法
arrayObject.slice(start,end)
参数 | 描述 |
---|---|
start | 必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。 |
end | 可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。 |
返回值
返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。
说明
请注意,该方法并不会修改数组,而是返回一个子数组。如果想删除数组中的一段元素,应该使用方法 Array.splice()。
提示和注释
注释:您可使用负值从数组的尾部选取元素。
注释:如果 end 未被规定,那么 slice() 方法会选取从 start 到数组结尾的所有元素。
详情请戳:https://www.w3school.com.cn/js/jsref_slice_array.asp
【1】如何实时统计输入框用户输入字数?
【2】怎么防止用户表单二次提交,你知道吗?
【3】页面如何调用组件内置方法?
❤如果文章对您有所帮助,就在文章的右上角或者文章的末尾点个赞吧!(づ ̄ 3 ̄)づ
❤如果喜欢大白兔分享的文章,就给大白兔点个关注吧!(๑′ᴗ‵๑)づ╭❤~
❤对文章有任何问题欢迎小伙伴们下方留言或者入群探讨【群号:708072830】
❤鉴于个人经验有限,所有观点及技术研点,如有异议,请直接回复讨论(请勿发表攻击言论)。