JavaScript的值传递和引用传递

一:  JavaScript有5种基本的数据类型:布尔、null、undefined、String和Number。这些基本类型在赋值的时候是通过值传递的方式。

另外一种复杂的数据类型object(Array、Function和Object)它们通过引用来传递。

 

数据类型

转换为true的值

转换为false的值

Boolean

true

false

String

任何非空字符串

“”(空字符串)

Number

任何非0数字

0和NaN(not a number)

Object

任何对象

null

Undefined

不适用  

undefined

二:引用传递---内存地址不能改变,属性值可以改变

对象是通过引用传递,而不是值传递。也就是说,变量赋值只会将地址(#001)传递过去,一旦地址内容改变则使用这个地址的所有变量的值也会改变

    说明:

      var a=[1];

  var b=a; 

  变量与地址的对应关系:

变量

地址

对象

a

#001

[1]

b

#001

 

栗子1

Var a=[1,2,3];

Var b=a;

a.push(78);//或者是b改变,b.push(78);,结果一样的

console.log(a);//[1,2,3,78]

console.log(b);//[1,2,3,78]

 

有个坑:重新赋值==换了一个新的内存地址,则b不改变

Var a =[1,2,3,4]; var b=a; a=[6,7,8,9];console.log(b) //1,2,3,4 只用引用地址里面的值改变了,可以一个一个添加进去

var a =[1,2,3,4];  a=[6,7,8,9];var b=a; console.log(b)//6,7,8,9  引用地址的同时也取了值

引用重新赋值

如果我们将一个已经赋值的变量重新赋值,那么它将包含新的数据或则引用地址

var b = { first: 'fundebug.com'};

b = { second: 'fundebug.cn'};

obj从指向第一个对象变为指向第二个对象。

如果一个对象没有被任何变量指向,就如第一个对象(地址为#001),JavaScript引擎的垃圾回收机制会将该对象销毁并释放内存。

变量

地址

对象

b

#001

{first: ‘fundebug.com’}

 

#002

{second: ‘fundebug.cn’}

 

 

 

对于引用类型的变量,=====只会判断引用的地址是否相同,而不会判断对象具体里属性以及值是否相同,

如果两个变量指向相同的对象,则返回true

如果是不同的对象,及时包含相同的属性和值,也会返回false

栗子2:

Var a={name:’lili’};

Var b=a;

Console.log(a===b)//true

栗子3

Var c=[1,2,3,45];

Var d=[1,2,3,45];

Console.log(c===d)//false

如果想判断两个不同的对象的值是否相同,一个简单的方法就是将它们转换为字符串然后判断。

栗子4

var cstr = JSON.stringify(c);

var dstr = JSON.stringify(d);

 

console.log(c === d); // true

纯函数

对于一个函数,给定一个输入,返回一个唯一的输出。除此之外,不会对外部环境产生任何附带影响。我们机会称该函数为纯函数。所有函数内部定义的变量在函数返回之后都被垃圾回收掉。

但是,如果函数的输入是对象(Array, Function, Object),那么传入的是一个引用。对该变量的操作将会影响到原本的对象。

因此,很多数组函数,比如Array.mapArray.filter是以纯函数的形式实现。虽然它们的参数是一个数组变量,但是通过深度拷贝并赋值给一个新的变量,然后在新的数组上操作,来防止原始数组被更改。

我们来看一个例子:

栗子6

function changeAgeImpure(person) {

person.age = 25;

return person;

}

var alex = {

name: 'Alex',

age: 30

};

var changedAlex = changeAgeImpure(alex);

console.log(alex); // { name: 'Alex', age: 25 }

console.log(changedAlex); // { name: 'Alex', age: 25 }

 

在非纯函数changeAgeImpure中,将对象personage更新并返回。原始的alex对象也被影响,age更新为25。

让我们来看如何实现一个纯函数:

栗子7

function changeAgePure(person) {

var newPersonObj = JSON.parse(JSON.stringify(person));

newPersonObj.age = 25;

return newPersonObj;

}

var alex = {

name: 'Alex',

age: 30

};

var alexChanged = changeAgePure(alex);

console.log(alex); // { name: 'Alex', age: 30 }

console.log(alexChanged); // { name: 'Alex', age: 25 }

 

我们通过JSON.sringify将对象变为一个字符串,然后再通过JSON.parse将字符串变回对象。通过该操作会生成一个新的对象。

栗子8

function changeAgeAndReference(person) {

person.age = 25;//对于personObj1:可以修改引用传递的属性值

person = {// 对于personObj1:不能修改引用传递的内存地址

name: 'John',

age: 50

};

 

return person;

}

var personObj1 = {

name: 'Alex',

age: 30

};

var personObj2 = changeAgeAndReference(personObj1);

console.log(personObj1); // {name: "Alex", age: 25}

console.log(personObj2); // {name: "John", age: 50}

 

posted @ 2018-07-20 10:36  青橙娃娃  阅读(82)  评论(0编辑  收藏  举报