JavaScript是通过引用传递还是通过值传递?

下面是一个来自JavaScript: The Good Parts的例子。我对矩形函数的参数很困惑。它实际上是未定义的,并在函数内部重新定义。没有原始参考文献。如果我从函数参数中删除它,内部区域函数就不能访问它。

它是一个闭包吗?但是没有返回函数。

var shape = function (config) {
    var that = {};
    that.name = config.name || "";
    that.area = function () {
        return 0;
    };
    return that;
};

var rectangle = function (config, my) {
    my = my || {};
    my.l = config.length || 1;
    my.w = config.width || 1;
    var that = shape(config);
    that.area = function () {
        return my.l * my.w;
    };
    return that;
};

myShape = shape({
    name: "Unhnown"
});

myRec = rectangle({
    name: "Rectangle",
    length: 4,
    width: 6
});

console.log(myShape.name + " area is " + myShape.area() + " " + myRec.name + " area is " + myRec.area());

当前回答

“全局”JavaScript变量是窗口对象的成员。您可以将引用作为窗口对象的成员访问。

var v = "initialized";

function byref(ref) {
  window[ref] = "changed by ref";
}

byref((function(){for(r in window){if(window[r]===v){return(r);}}})());
// It could also be called like... byref('v');
console.log(v); // outputs changed by ref

注意,上面的例子不适用于函数中声明的变量。

其他回答

为了创建一个使用const的简单示例…

const myRef = { foo: 'bar' };
const myVal = true;

function passes(r, v) {
  r.foo = 'baz';
  v = false;
}

passes(myRef, myVal);

console.log(myRef, myVal); // Object {foo: "baz"} true

函数参数通过值或共享传递,但在JavaScript中从来不通过引用!

"值

基元类型按值传递:

var num = 123, str = “foo”; 函数 f(num, str) { 数字 += 1; str += “bar”; console.log(“inside of f:”, num, str); } f(数字, str); console.log(“Out of f:”, num, str);

函数作用域中的重赋在周围的作用域中是不可见的。

这也适用于string,它是一个复合数据类型,但不可变:

Var STR = "foo"; 函数f(str) { Str [0] = "b";//不起作用,因为字符串是不可变的 Console.log ("in of f:", str); } f (str); Console.log ("outside of f:", str);

Call-by-Sharing

对象,也就是说所有不是基元的类型,都是通过共享传递的。保存对象引用的变量实际上只保存该引用的副本。如果JavaScript采用引用调用求值策略,则变量将保存原始引用。这是共享和引用之间的关键区别。

这种区别的实际后果是什么?

Var o = {x: "foo"}, p = {y: 123}; 函数f(o, p) { O.x = "bar";/ /突变 P = {x: 456};/ /重新分配 Console.log ("o within f:", o); Console.log ("p inside of f:", p); } f (o p); Console.log ("o outside of f:", o); Console.log ("p outside of f:", p);

突变是指修改现有对象的某些属性。变量所绑定的引用副本和引用该对象的引用副本保持不变。因此,突变在调用者的作用域中是可见的。

重赋值意味着替换绑定到变量的引用副本。由于它只是一个副本,持有同一引用副本的其他变量不受影响。因此,重赋在调用者的作用域中是不可见的,就像在引用调用求值策略中那样。

关于ECMAScript中评估策略的进一步信息。

我的两分钱....JavaScript是通过引用还是值传递参数无关紧要。真正重要的是赋值还是变异。

我在这个链接里写了一个更长的,更详细的解释。

当你传递任何东西(无论是一个对象还是一个原语)时,JavaScript所做的只是在函数内部分配一个新变量……就像使用等号(=)一样。

这个参数在函数内部的行为和你用等号赋值一个新变量的行为是完全一样的。举几个简单的例子。

var myString = '测试字符串1'; //赋值-指向myString相同位置的链接 var sameString = myString; //如果我改变了sameString, myString将不会改变, //它只是重新赋值给一个全新的字符串 sameString = '新字符串'; console.log (myString);//记录'测试字符串1'; console.log (sameString);//记录'新字符串';

如果我将myString作为参数传递给一个函数,它的行为就好像我简单地将它赋给了一个新变量。现在,让我们做同样的事情,但是用一个函数而不是简单的赋值

函数myFunc(sameString) { / /重置手术……同样,它不会修改myString sameString = '新字符串'; } var myString = '测试字符串1'; //它的行为与sameString = myString相同 myFunc (myString); console.log (myString);//再次,日志'测试字符串1';

当你将对象传递给函数时,你可以修改对象的唯一原因是你没有重新赋值…相反,对象可以更改或突变....同样,它的工作方式是一样的。

var myObject = { name: 'Joe'; }

// Assignment - We simply link to the same object
var sameObject = myObject;

// This time, we can mutate it. So a change to myObject affects sameObject and visa versa
myObject.name = 'Jack';
console.log(sameObject.name); // Logs 'Jack'

sameObject.name = 'Jill';
console.log(myObject.name); // Logs 'Jill'

// If we re-assign it, the link is lost
sameObject = { name: 'Howard' };
console.log(myObject.name); // Logs 'Jill'

如果我将myObject作为参数传递给一个函数,它的行为就好像我简单地将它赋给了一个新变量。同样的事情,同样的行为,但是是一个函数。

函数myFunc(sameObject) { //我们改变了对象,所以myObject也得到了改变…就像以前一样。 sameObject.name = 'Jill'; //但是,如果我们重新分配它,链接就丢失了 sameObject = { 名称:“霍华德” }; } var myObject = { 名称:“乔” }; //这就像我们说sameObject = myObject一样; myFunc (myObject); console.log (myObject.name);//日志'Jill'

每次将变量传递给函数时,你都是在“赋值”给参数的名称,就像使用等号一样。

永远记住等号=表示赋值。 将参数传递给函数也意味着赋值。 它们是相同的两个变量以完全相同的方式连接在一起。

修改一个变量影响另一个变量的唯一情况是底层对象发生变化。

区分对象和原语是没有意义的,因为它的工作方式就像你没有一个函数,只是用等号赋值给一个新变量一样。

“全局”JavaScript变量是窗口对象的成员。您可以将引用作为窗口对象的成员访问。

var v = "initialized";

function byref(ref) {
  window[ref] = "changed by ref";
}

byref((function(){for(r in window){if(window[r]===v){return(r);}}})());
// It could also be called like... byref('v');
console.log(v); // outputs changed by ref

注意,上面的例子不适用于函数中声明的变量。

JavaScript是按值传递的。

对于原语,则传递原语的值。对于对象,传递对象的引用“值”。

带对象的示例:

var f1 = function(inputObject){
    inputObject.a = 2;
}

var f2 = function(){
    var inputObject = {"a": 1};
    f1(inputObject);
    console.log(inputObject.a);
}

调用f2会将“a”值打印为2而不是1,因为引用被传递并且引用中的“a”值被更新。

使用primitive的示例:

var f1 = function(a){
    a = 2;
}
var f2 = function(){
    var a = 1;
    f1(a);
    console.log(a);
}

调用f2会将“a”值打印为1。