javascript - JavaScript是传递引用或者按值传递参数的语言?

  显示原文与译文双语对照的内容

基元类型( 数字,字符串,等等 ) 通过值传递,但对象未知,因为它们可以是 passed-by-value ( 如果我们认为持有对象的变量实际上是对对象的引用) 和 passed-by-reference ( 当我们认为对象的变量持有对象本身时) 。

尽管最终并不重要,但我想知道如何正确地给出传递约定的参数。 是否有来自JavaScript规范的摘录,该规范定义了关于?

时间:

在Javascript中很有趣。请考虑以下示例:


function changeStuff(a, b, c)
{
 a = a * 10;
 b.item ="changed";
 c = {item:"changed"};
}

var num = 10;
var obj1 = {item:"unchanged"};
var obj2 = {item:"unchanged"};

changeStuff(num, obj1, obj2);

console.log(num);
console.log(obj1.item); 
console.log(obj2.item);

<!-- results pane console output; see http://meta.stackexchange.com/a/242491 -->
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

这将生成输出:

 
10
changed
unchanged

 

如果是纯传递,那么改变 obj1.item 对函数外部的obj1 没有影响。 如果是纯粹通过引用,那么一切都会改变。 num 将是 100obj2.item 将读取 "changed"

相反的情况是传入的项目通过值传递。 但是,通过数值传递的项本身是引用。 从技术上说,这叫做 call-by-sharing

实际上,这意味着如果你更改参数本身( 与 numobj2 一样),这不会影响输入到参数的项目。 但是如果你更改参数的内部,那么它将传播到( 与 obj1 一样) 。

它总是通过值传递,但对于对象来说,变量的值是一个引用。 正因为如此,当你通过一个对象并改变其成员,这些变化存在以外的功能。 这使得它看起来像以引用的方式传递。 但是如果你改变对象变量的值,你会发现改变并不持久,证明它实际上是通过值传递的。

例如:


function changeObject(x) {
 x = {member:"bar"};
 alert("in changeObject:" + x.member);
}

function changeMember(x) {
 x.member ="bar";
 alert("in changeMember:" + x.member);
}

var x = {member:"foo"};

alert("before changeObject:" + x.member);
changeObject(x);
alert("after changeObject:" + x.member);/* change did not persist */

alert("before changeMember:" + x.member);
changeMember(x);
alert("after changeMember:" + x.member);/* change persists */

输出:


before changeObject: foo
in changeObject: bar
after changeObject: foo

before changeMember: foo
in changeMember: bar
after changeMember: bar

Javascript总是 pass-by-value,一切都是一个值类型。 对象是值,作为参数传递,对象函数是值本身,通过值传递,记住函数是Javascript中的一级对象。 另外,关于javascript的概念,一切都是一个对象,这是错误的,字符串、数字、bools, null, undefineds原语,有时他们可以利用一些成员函数和属性继承基本原型,但这只是为了方便起见,这并不意味着他们是对象本身。 尝试以下选项以供参考


x ="test";
alert( x.foo );
x.foo = 12;
alert( x.foo );

在这两个通知中,你将发现要定义的值。

关于复制,传递和按值比较的非常详细的解释和参考在本章中是"javascript: 确定的指南"书籍。

在我们通过引用来处理对象和数组的主题之前,我们需要澄清一个命名点。 短语"通过引用传递"可以有几个含义。 对于一些读者来说,这个短语是指一个函数调用技术,它允许一个函数给它的参数赋值,并让那些修改后的值在函数之外可见。 这不是本书中使用的术语。 这里,我们的意思是对对象或者数组--的引用不是对象本身--传递给函数。 函数可以使用引用修改数组的对象或者元素的属性。 但是,如果函数用一个对新对象或者数组的引用覆盖引用,则该修改在函数外部不可见。 熟悉这个术语的其他含义的读者可能会说,对象和数组是通过值传递的,但传递的值实际上是引用而不是对象本身。

还有一件事我还是想不通。 检查下面的代码。任何想法?


function A() {}
A.prototype.foo = function() {
 return 'initial value';
}


function B() {}
B.prototype.bar = A.prototype.foo;

console.log(A.prototype.foo());//initial value
console.log(B.prototype.bar());//initial value

A.prototype.foo = function() {
 return 'changed now';
}

console.log(A.prototype.foo());//changed now
console.log(B.prototype.bar());//Why still 'initial value'???

我发现的最简洁的解释是在 AirBNB风格指南中:

  • 基元: 当你访问一个基本类型时,你直接在它的值上工作

    • 字符串
    • 号码
    • 布尔型
    • 未定义

比如:


var foo = 1,
 bar = foo;

bar = 9;

console.log(foo, bar);//=> 1, 9

  • 复杂:当你访问一个复杂类型的引用它的价值

    • 对象
    • 数组
    • 函数

比如:


var foo = [1, 2],
 bar = foo;

bar[0] = 9;

console.log(foo[0], bar[0]);//=> 9, 9

I.e 。有效的基元类型通过值传递,复杂类型通过引用传递。

将参数传递给JavaScript中的函数类似于用指针中的指针值传递参数:


/*
The following C program demonstrates how arguments
to JavaScript functions are passed in a way analogous
to pass-by-pointer-value in C. The original JavaScript
test case by @Shog9 follows with the translation of
the code into C. This should make things clear to
those transitioning from C to JavaScript.

function changeStuff(num, obj1, obj2)
{
 num = num * 10;
 obj1.item ="changed";
 obj2 = {item:"changed"};
}

var num = 10;
var obj1 = {item:"unchanged"};
var obj2 = {item:"unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item); 
console.log(obj2.item);

This produces the output:

10
changed
unchanged
*/

#include <stdio.h>
#include <stdlib.h>

struct obj {
 char *item;
};

void changeStuff(int *num, struct obj *obj1, struct obj *obj2)
{
//make pointer point to a new memory location
//holding the new integer value
 int *old_num = num;
 num = malloc(sizeof(int));
 *num = *old_num * 10;
//make property of structure pointed to by pointer
//point to the new value
 obj1->item ="changed";
//make pointer point to a new memory location
//holding the new structure value
 obj2 = malloc(sizeof(struct obj));
 obj2->item ="changed";
 free(num);//end of scope
 free(obj2);//end of scope
}

int num = 10;
struct obj obj1 = {"unchanged" };
struct obj obj2 = {"unchanged" };

int main()
{
//pass pointers by value: the pointers
//will be copied into the argument list
//of the called function and the copied
//pointers will point to the same values
//as the original pointers
 changeStuff(&num, &obj1, &obj2);
 printf("%dn", num);
 puts(obj1.item);
 puts(obj2.item);
 return 0;
}

...