在下面的代码中,我们正在传递一个对象。因此,根据JavaScript的规定,我们正在传递一个引用并进行操作。
但是警报会提示10而不是12。为什么?
var a = new Number(10);
x(a);
alert(a);
function x(n) {
n = n + 2;
}
但是警报会提示10而不是12。为什么?
var a = new Number(10);
x(a);
alert(a);
function x(n) {
n = n + 2;
}
n
是局部于 x
的变量,并且首先它被设置为与全局变量 a
相同的引用。然后评估右侧的表达式 n + 2
,结果为一个数字(原始类型)。
赋值语句的左侧,n
,从未被评估过,在这里它只是一个标识符。因此,我们的局部变量现在被设置为右侧表达式的原始值。由 a
引用的值实际上从未被修改过。参见var a = new Number(10);
x(a);
alert(a); // 10
function x(n) {
alert(typeof n); // object
n = n + 2;
alert(typeof n); // number
}
n + 2
即使n
确实是一个Number
对象实例,这也会导致一个新的“本地数字”。
然后将值分配给n
只会更改本地变量n
所引用的内容,而不会更改Number
对象实例。您可以通过以下方式查看:
n = new Number(10);
console.log(typeof n); // ---> "object"
console.log(n + 2); // ---> 12
console.log(typeof (n+2)); // ---> "number"
n = n + 2;
console.log(typeof n); // ---> "number"
function foo(setter) {
setter(42);
}
funciton bar() {
var x = 12;
foo(function(newx){x = newx;});
console.log(x); // ---> 42
}
x = new Number(5)
或者 x = 5
,那么没有任何操作可以使 x
保持相同的引用但具有不同的值。当我执行 console.log(new Number(5))
时,它会输出 Number {[[PrimitiveValue]]: 5}
。但是我假设你不能改变那个 [[PrimitiveValue]]
,对吗? - soktinpkvalueOf()
方法的对象,该方法可以在数学表达式中像数字一样运行,但具有可变状态,您可以控制它。 - 6502Number
实际上是通过值直接传递的,而不是通过中介指针传递的。但是,由于这些类型是不可变的,因此在这种情况下,传值和调用对象共享之间没有可观察到的行为差异,因此您可以大大简化您的心理模型,只需将所有东西视为调用对象共享。只需将这些特殊情况解释为内部编译器优化,您就无需担心。function isEcmascriptPassByValue(foo) {
foo.push('More precisely, it is call-by-object-sharing!');
foo = 'No, ECMAScript is pass-by-reference.';
return;
}
var bar = ['Yes, of course, ECMAScript *is* pass-by-value!'];
isEcmascriptPassByValue(bar);
console.log(bar);
// Yes, of course, ECMAScript *is* pass-by-value!,
// More precisely, it is call-by-object-sharing!
struct MutableCell
{
public string value;
}
class Program
{
static void IsCSharpPassByValue(string[] foo, MutableCell bar, ref string baz, ref MutableCell qux)
{
foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.";
foo = new string[] { "C# is not pass-by-reference." };
bar.value = "For value types, it is *not* call-by-sharing.";
bar = new MutableCell { value = "And also not pass-by-reference." };
baz = "It also supports pass-by-reference if explicitly requested.";
qux = new MutableCell { value = "Pass-by-reference is supported for value types as well." };
}
static void Main(string[] args)
{
var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" };
var corge = new MutableCell { value = "For value types it is pure pass-by-value." };
var grault = "This string will vanish because of pass-by-reference.";
var garply = new MutableCell { value = "This string will vanish because of pass-by-reference." };
IsCSharpPassByValue(quux, corge, ref grault, ref garply);
Console.WriteLine(quux[0]);
// More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.
Console.WriteLine(corge.value);
// For value types it is pure pass-by-value.
Console.WriteLine(grault);
// It also supports pass-by-reference if explicitly requested.
Console.WriteLine(garply.value);
// Pass-by-reference is supported for value types as well.
}
}
让我用例子来回答这个问题:
function modify(obj) {
// modifying the object itself
// though the object was passed as reference
// it behaves as pass by value
obj = {c:3};
}
var a = {b:2}
modify(a);
console.log(a)
// Object {b: 2}
function increment(obj) {
// modifying the value of an attribute
// working on the same reference
obj.b = obj.b + 1;
}
var a = {b:2}
increment(a);
console.log(a)
// Object {b: 3}
function augument(obj) {
// augument an attribute
// working on the same reference
obj.c = 3;
}
var a = {b:2}
augument(a);
console.log(a)
// Object {b: 2, c: 3}
var a = new Number(10);
x(a);
alert(a);
function x(n) {
n = n + 2; // NOT VALID as this would essentially mean 10 = 10 + 2 since you are passing the 'value' of a and not 'a' itself
}
你需要编写以下内容才能使其正常工作
var a = new Number(10);
x(a);
alert(a);
function x(n) {
a = n + 2; // reassign value of 'a' equal to the value passed into the function plus 2
}
function doThis(param1, param2) {
param1++;
if(param2 && param2.value) {
param2.value++;
}
}
var initialValue = 2;
var initialObject = {value: 2};
doThis(initialValue, initialObject);
alert(initialValue); //2
alert(initialObject.value); //3