宝哥软件园

通过例子理解js函数中参数的传递

编辑:宝哥软件园 来源:互联网 时间:2021-08-22

先看一个JS笔测试:

var Setobj=function(o){ o . name=' Xiaoming ';o={ };o.name=' xiaohong}var p={name:'xixi ',age :24 };setbj(p);console . log(p);答案是{{name:xiaoming,age 24 };};

在JavaScript中,函数参数默认为引用类型。

一、函数传递值类型:

代码示例如下:

函数AddNum(num){ num=10;返回数字;} var num=10var结果=AddNum(num);console . log(num);console.log(结果);上述代码的弹出值分别为:10和20。下面我们来分析一下:

声明变量num并将其复制为10。num是一个值类型。将参数传递给函数时,会将该值的副本传递给函数。因此,函数执行后,num本身的值不会改变,函数中改变的值只是一个副本。

二.传递引用类型:的函数

函数setName(obj){ obj.name='青岛新锐';} var web=new Object();Web.name='蚁族';setName(web);console . log(web . name);上述代码的弹出值为:“青岛新锐”。下面我们来分析一下:

声明一个对象web,它是一个引用类型。当传递参数给函数时,它是被传递的web对象的引用,也就是这个对象的内存地址。因此,修改函数中属性的对象是在函数外创建的对象本身。

三.加深理解:

函数setName(obj){ obj.name='青岛新锐';obj=新对象();Obj.name='蚁族';} var web=new Object();setName(web);console . log(web . name);上述代码的弹出值为:青岛新锐。很多人可能会认为“蚁族”会冒出来。让我们简单分析一下:

在函数外部创建一个对象,并将该对象的引用分配给变量web。网络将对象的存储地址存储在内存中。向函数传递参数时,它是在函数外部创建的对象的地址。在函数中,为外部创建的对象创建一个自定义属性名,并将其分配为“青岛新锐”,然后创建一个新对象,并将新对象的地址分配给obj。此时,obj没有指向在函数外部创建的对象,因此外部对象的name属性不会改变。

其他语言的程序员很难这样写。我们在实际发展中应该避免这种方式,因为它会造成全球范围的污染。最近在读《javascript高级程序设计》的时候,遇到了js交付模式的问题,花了一些时间,但是终于明白了。

数据类型

在javascript中,数据类型可以分为两类:

基元类型的值,如undefined、null、boolean、number、string。引用类型值是对象类型,如对象、数组、函数、日期等。变量的复制

众所周知,js中变量的基本类型和引用类型保存方式不同,导致变量的复制方式也不同。如果您将基本类型值从一个变量复制到另一个变量,您将克隆前一个值,然后将克隆的值分配给后者,因此这两个值是完全独立的,但它们的值是相同的。

var num1=10var num2=num1console . log(num 2);//10上面num1中存储的值是10。当num1的值赋给num2时,num2的值也是10。但这两个10完全独立。num2中的10只是克隆出来的,相当于写了一个word文档放在num1的文件夹里。然后我复制这个word文档,叫做word副本,然后把这个副本放到num2的文件夹里。这两个word文档完全相同。修改任何一个都不会影响任何一个。

num 2=1;console . log(num 1);//10 console . log(num 2);//11从上面可以看出,num2的值被修改了,但是num1的值没有改变。让我们看看引用类型的复制。当您将引用类型的值从一个变量复制到另一个变量时,您也将把变量对象中存储的值复制到为新变量分配的空间中。

var obj 1={ name : ' 111 ' };var obj2=obj1console . log(obj 2 . name);//111 obj 2 . name=' 222 ';console . log(obj 1 . name);//222第一个打印结果是“111”,我们很容易理解,但是第二个打印结果是“222”,有点莫名其妙。这就是引用类型和基本类型的区别。复制对象时,不会在堆内存中新生成相同的对象,而只会添加一个保存指向该对象的指针的变量。obj1的值被复制到obj2,这个值的副本实际上是一个指针,它指向一个存储在堆中的Object,也就是说创建一个新的内存地址并传递给obj2,两个变量obj1和obj2同时指向同一个对象。当这个对象改变时,它们的值也会改变,也就是说,它们中任何一个所做的改变都会反映在另一个上。下面的简化图可能更清楚。

函数参数的传递

《js高级程序设计》对参数传递的描述如下:函数的所有参数都是按值传递的,也就是说,将函数外部的值复制到函数内部的参数,与将值从一个变量复制到另一个变量是一样的。因此,如果我们能理解变量的复制,那么参数的传递就很简单了。让我们从一个基本类型的例子开始。

var计数=10;函数num(num 1){ num 1=1;返回num1} var result=num(count 1);console.log(结果);//1 con sole . log(count);//10,没有改成1,很容易理解。事实上,创建了count的副本,然后将count的值传递给参数。因为参数值是在函数中定义的,所以1覆盖10,最终结果返回1,但计数没有改变。看一个传递对象的例子。

var person={ name : ' Tom ' };function obj(peo){ peo . name=' Jerry ';返回peo} var result=obj(person);console . log(result . name);//Jerry console . log(person . name);//Jerry在上面的例子中,person被复制传递到obj(),peo和person指向同一个对象,但是在peo中修改了name属性,这实际上修改了他们都指向的对象的name属性,对应的外部person引用的name属性也发生了变化,所以Jerry被打印了出来。其实我第一眼感觉引用类型的参数都是引用传递的,这是我最初的错误。让我们看另一个例子。

var person={ name : ' Tom ' };function obj(peo){ peo={ name : ' Jerry ' };返回peo} var result=obj(person);console . log(result . name);//Jerry console . log(person . name);//Tom在上面的例子中,函数中重新定义了一个对象,即堆内存中有两个对象。外部人员指向旧对象,传入参数后指向新定义的对象,所以调用后返回的值就是新定义对象的值。如果参数是通过引用传递的,那么person.name打印的结果就是Jerry,由此可以得出参数是通过值传递的结论(有些地方叫做通过共享传递)。

我们用老罗推荐的《人类简史》来形象化,描述的不是很好。简史第一章的标题是“认知革命”,我们把它的名字改成了“人”。根据其背后的页码,我们可以直接找到“认知革命”的内容,这是佩森所指向的对象。第二章是“农业革命”,我们称之为“结果”。它的子目录有一个“内存过载”(改名为“peo”)的部分,也可以直接

现在我们把“人”抄成“peo”,第二章“peo”的那一节就变成了“人”,但我们根据第一章“peoson”找到的是第一章的内容,因为它们指向不同的内容节,互不干扰。在这里,堆内存是每一章的内容,而第一章和第二章的内容是两个不同的对象,它们彼此无关。因此,当打印外部person.name时,结果仍然是前一个对象的属性值。

结论

总之,参数是通过js中的值传递的。我写的例子比较粗糙,《javascript高级程序设计》中的例子更清晰更容易理解。

以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。

更多资讯
游戏推荐
更多+