写冒泡排序时,遇到一个问题:数组
function bubbleSort(arr){ var temp = 0; console.log("传入的数组:"); console.log(arr); for(var i = 0;i<arr.length;i++){ //循环arr.length-1次 console.log("外层第"+i+"次循环===============start"); for(var j = 0;j<arr.length-1;j++){ //循环arr.length-1-1次 if(arr[j]<arr[j+1]){ //倒叙排列数组:若是相邻的两个,前面那个比后面那个小,就互换 temp = arr[j]; // —┐ arr[j] = arr[j+1]; // —├—借助中间变量将数组中的两个值进行互换 arr[j+1] = temp; // —┘ } console.log("内层"+j+"次循环"); console.log(arr); } console.log("外层第"+i+"次循环===============end"); } return arr; }
var array = [2,3,9,5,7,1,8]; var sortArray = bubbleSort(array); console.log("array "+array);//array 9,8,7,5,3,2,1 console.log("sortArray "+sortArray);//sortArray 9,8,7,5,3,2,1 //好奇为何array也被排序了吗?
看下面的研究:函数
我首先想到的是,是否是return的问题。难道我脑子里少记了一个return的不知道的关键做用?性能
先测试一下:测试
function foo(bar){ bar = 1; return bar; //return 3; } var a = 0; var b = foo(a); console.log(a) //0 console.log(b) //1 //若是return 3 就获得3 //不加return, function foo2(bar2){ bar2 = 1; } var a2 = 0; var b2 = foo2(a2); console.log(a2) //0 console.log(b2) //undefined
return就是用来返回函数值的,它真的没什么特殊的神奇的功效。
其实就是直接删掉return,试一下就知道是否是了,我怎么会怀疑这个。
等等,为何上面的a不会被修改掉啊,难道跟a是数字有关?
那这里的问题应该就出在数组上。spa
数组怎么了?关于JavaScript的数据类型和赋值原理的这一块知识,个人脑子里模糊了。3d
先来段代码试试:指针
function foo(bar){ bar = [1,2,3,4]; return bar; } var a = [1,2,3]; var b = foo(a); console.log(a) //[1,2,3] console.log(b) //[1,2,3,4] function foo2(bar2){ bar2[0] = 0; return bar2; } var a2 = [1,2,3]; var b2 = foo(a2); console.log(a2) //[0,2,3] console.log(b2) //[0,2,3]
两个函数一样是数组,为何结果不同?code
上面缘由在于数组是引用数据类型对象
关于js数据类型的研究
js中数据类型分为:
string,number,boolean,[],{},null,undefined
字符串,数字,布尔,数组,对象,null,undefinedblog
null和undefined区别????-------------------------------------undefined:声明变量但未初始化,null,找不到该对象
null==undefined//true
null===undefined//false
上面的数据类型能够分类
原始类型和引用类型
原始类型:undefined,null,boolean,number,string
引用类型:[],{}
在许多语言中,字符串string都被看做引用类型,而非原始类型,由于字符串的长度是可变的,可是js打破了这一传统。
可是,JavaScript拥有动态类型的,也就是说,一个变量能够被赋值成不一样的类型。
那么咱们接下来就不考虑纠结变量是哪一种数据类型了,每一个数据类型有怎样怎样了了,咱们直接从 变量的值 的角度 来继续思考
在js中,一个变量能够拥有两种类型的值(参考上面数据类型)
原始值和引用值
原始值:存储在栈(stack)中的简单数据段,也就是说,他们的值直接存储在变量访问的位置
引用值:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处。
因此,在为变量赋值时,JavaScript的解释程序必须先判断该值是原始类型仍是引用类型。
要实现这一点,JavaScript解释程序则需尝试判断该值是不是JavaScript的原始类型之一。原始类型有哪些上面已经说过了。
若是是原始类型,因为原始类型占据的空间是固定的,因此在内存中,他们被存储在栈中,这样子便于快速查询变量的值。(关于string长度可变看上面)
若是是引用类型,那么它的存储空间将从堆中分配。缘由是由于,引用值的大小会改变,因此不能把他们放在栈中,不然会下降变量查询的速度。所以咱们就把该对象在堆中的地址放在栈中。地址的大小是固定的,因此对变量性能无任何负面影响。
如图所示:
------------------------------------------------这上面相关知识来源:http://www.w3school.com.cn/js/pro_js_value.asp
------------------------------------------------这下面相关知识来源:https://www.zhihu.com/question/26042362/answer/31903017
因此上面的出现的问题也就好解释了。
能够简化成这样:
var a = [1,2,3]; var b = a; a = [4,5,6]; alert(b); //[1,2,3] var a = [1,2,3]; var b = a; a.pop();//内置函数,删掉数组最后一个 alert(b); //[1,2]
图解就是这样:
就算是调用函数
var b = foo(a)
只要这个函数里面的操做直接操做传入的数组对象自己,那么就是在操做堆中的对象。
就会修改到自身。
只要是没有操做它自己,而是在堆里建立了一个新的对象,而后从新将栈中b的引用地址修改过去。
就不会修改自身。
拓展阅读;https://zhuanlan.zhihu.com/p/24080761