为什么对象不相等?
var obj1 = { name: 'haolucky' }
var obj2 = { name: 'haolucky' }
obj1 === obj2 // false
obj1 == obj2 // false
在声明 obj1 = { name: 'haolucky' }
时,实际上是在堆内存中创建一个对象 { name: 'haolucky' }
,而 obj1
存储的是这个对象在堆内存中的地址,即 obj1
是一个指针,指向了内存中这个对象 { name: 'haolucky' }
。
同样的道理,obj2
也是在内存中开辟一个空间,创建了一个对象 { name: 'haolucky' }
,并指向这个地址。
综上所述,因为 obj1
和 obj2
是两个不同的地址,所以两者不相等;在 JavaScript
中,引用类型(对象、数组、正则、Date、函数)的比较,实际上是比较指针是否指向存储器中的同一段地址,只有指向同样的地址才能相等。
对于引用类型,指的是保存在内存中的对象。如果是同一对象,则值相同,不同对象则值不同。
基本类型参数按值传递
// 参数都是按值传递的
var str1 = 1
var str2 = 2
function handle(str1, str2){
str1++
str2++
console.log(str1, str2) // 2, 3
return str1 + str2
}
handle(str1, str2)
console.log(str1) // 1
console.log(str2) // 2
上面的函数中的参数是实参的拷贝,并不会影响全局的变量
引用类型参数按值传递
function change(obj) {
obj.age = 16
obj = new Object()
obj.age = 18
}
var obj = new Object()
change(obj)
console.log(obj.age) // 16
调用 change
函数时,传过去的 obj
参数是实例 new Object()
在内存中的地址,是按值传递,它们指向同一个地址对应的对象。如果改变里面的值,外面的实例也能相应的发生改变。obj = new Object()
重新给 obj
在内存中开辟了一个空间,指向了另外一个对象,所以不能修改外面实例的值。
1、实参将指向的内存地址传递给形参 ,按值传递的值指的是内存地址;
2、形参修改了它和实参共同指向的对象后,外部的实参会反映出来;
3、但形参始终无法修改实参指向的内存地址,即如果将形参指向新的对象,实参并不会指向新的对象。
使用案例:无返回值的带参void函数是没有返回值的,那么对于传入的参数在计算处理之后,怎么把结果返回呢?软件开发中实际上最常用的两种方式:指针和引用!在主程序中直接声明一个变量,然后把这个变量的引用或者指针作为参数直接传递给void函数,当void函数在做处理时,直接将结果写到引用参数或者指针指向的主函数变量,这样就间接实现了“返回值”。一可以让代码更简洁,二是能减少内存空间的占用。
在JavaScript中,函数的参数传递方式都是按值传递,没有按引用传递的参数。
但是JavaScript中有保存引用的对象,比如数组,它们是按引用传递的。
function curve(arr, amount) {
for(var i =0; i < arr.length; ++i) {
arr[i] += amount;
}
}
var grades = [1,2,3,4,5,6]
curve(grades, 5)
print(grades); // [6, 7, 8, 9, 10]
连续赋值
var obj1 = {n: 1}
var obj2 = obj1
/* obj1.x = obj1
console.log(obj2, obj1) // obj2 = {n:1,x:{n:1,x{...}}},obj1 = {n:1,x:{n:1,x{...}}} */
obj1.x = obj1 = {n: 3}
console.log(obj1, obj2, obj1.x, obj2.x) // {n:3}, {n:1,x:{n:3}}, undefined, {n:3}
obj1
、obj2
都指向了对象A
.
运算符的优先级高于=
先计算obj1.x
,并且此处的obj1
指向是初始对象A
obj1.x = undefined
对象A此时变成了{n:1,x:undefined}
即obj1 = {n:1,x:undefined} obj2 = {n:1,x:undefined}
然后从右至左依次运算
obj1 = {n:3}
指针发生了改变
obj1
重新指向一个新的对象B{n:3}
即obj1 = {n:3}
此时obj2 = {n:1,x:undefined}
obj1.x = obj1
直接赋值,并不会改变指针
这个obj1.x
中的obj1
就是第一步的初始对象A,而后面的obj1
在第二步的时候已经重新指向了新对象B
即obj1.x = {n:3}
相当于 ===>obj2.x = {n:3}
即obj2 = {n:1,x:{n:3}}
当打印obj1.x