【问题标题】:JavaScript objects as function parametersJavaScript 对象作为函数参数
【发布时间】:2011-06-23 12:36:52
【问题描述】:

使用 JavaScript,假设我有一个函数 X,并在该函数中创建了一个名为 objectX 的对象。函数 X 返回 objectX。稍后在代码函数 Z(somevar, anObject) 中接收 objectX 作为其参数之一。

现在在函数 Z 中,objectX 及其所有属性是否在函数 Z 中称为 anObject?

如果函数 Z 返回一个对象会发生什么?其余代码会将对象视为“objectX”还是“anObject”?

function X() {
    ...
    objectX = {};
    ...
    return objectX;
}

X();

function Z(anything, anObject) {
    ...
    return anObject
}

Z(something, objectX);

【问题讨论】:

  • 你真的需要更好地解释你在说什么。使用伪代码或其他东西。按照您的描述,函数 X 永远不会被调用。
  • 该代码无法运行。 X 函数永远不会被调用:Javascript 是区分大小写的,所以 x()' is something different than X()`...
  • @Martijn - 抱歉,这是打字机。我修好了。

标签: javascript object parameter-passing


【解决方案1】:

anObjectobjectX 都引用内存中的同一个空间,所以,随意命名,它始终是同一个对象。

祝你好运!

【讨论】:

  • @Gonzalo - 即使函数 Z 将对象返回为“anObject”,我仍然可以将其称为 objectX?
【解决方案2】:

这主要是范围问题。

function X() {
    // local objectX, only accessible through this name inside X()
    var objectX = {};
    objectX.foo = 'bar';
    return objectX;
}

function Z(somevar, anObject) {
    // anObject is passed in as a parameter
    // it's only accessible through this name inside Z()
    anObject.foo = somevar;
    return anObject;
}

// get the 'objectX' from X() and store it in global variable a
var a = X();

// pass the received 'objectX' into Z()
// note that the variable names objectX and anObject cannot be accessed
// because they are local variables of the functions X() / Z()
var b = Z('baz', a);

// a is now the same as b, they both reference the same var
// a.foo and b.foo both are set to 'baz'

【讨论】:

  • @igorw - 我认为您对范围的看法不正确。当您返回 objectX 时,它确实可以在函数之外作为“anObject”访问。我已经在我正在编写的程序中这样做了。我刚刚在我的编码中遇到了一种情况,我可能需要将 objectX 传递给函数 Z
  • @Ben 那么你可能做错了。如果您不使用 var 关键字,则 var 将成为全局变量(这很糟糕),并且可以从任何地方访问。
  • 我明白你的意思。谢谢。
【解决方案3】:

我相信一个例子是最好的教学方式。这是一些代码(click here 在 JS Bin 中查看):

// Defines the variable to keep track of how many objects X() defines.
var num = 1;

// Instantiate another variable to see if it is changed by Z().
var anObject;

// Creates an object with a comment and a random number.
function X() {
  // Create an object and give it a name.
  var objectX = {comment : "Creation #" + num};
  // Increase the value of num.
  num++;
  // Add another random number between 0 and 100 inclusively.
  objectX.randNum = Math.round(Math.random() * 100);
  // Return objectX.
  return objectX;
}

// Modifies the second parameter by adding the value of the first parameter.
function Z(somevar, anObject) {
  anObject.somevar = somevar;
  return anObject;
}

var objectX = X(), objectY = X();
objectX2 = Z('coolness', objectX);

// Notice that objectX is still the result of calling X() the first time.
alert("objectX.comment = " + objectX.comment);

// Notice that objectX is not equal to objectY.
alert("objectX === objectY evaluates to " + (objectX === objectY));

// Notice that objectX2 is the same thing as objectX.
alert("objectX === objectX2 evaulates to " + (objectX === objectX2));

// Notice that anObject is not defined.
alert("typeof anObject evaluates to " + (typeof anObject) + " after Z is called.");​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

alert("Now review the JavaScript code.");

如果通读 cmets,您会找到问题的答案。首先你会注意到,在函数 Z 中,由于我将 objectX 作为第二个参数传递,在函数内部,它可以被 anObject 引用。其次,您会注意到一旦在函数 Z 之外,anObject 不再引用 objectX。 cmets 还揭示了 JavaScript 中的其他真实情况。

【讨论】:

  • 我觉得我有点过头了。
【解决方案4】:

Javascript 具有函数范围。这意味着在函数中声明的每个变量都只能在该函数中访问。

如果你用var正确声明了objectX变量,如下:

function X() {
    ...
    var objectX = {};
    ...
    return objectX;
}

那么objectXX 函数中只能称为objectX。在其他地方,它将被称为您分配给它的任何变量。由于在您的代码中,您没有将 X() 的结果分配给任何东西,因此无法从任何地方访问 objectX

然而,这是 Javascript 更严重的设计缺陷之一:如果您显式声明一个变量(使用 var 语句或作为函数参数),该变量将自动变为全局变量。这意味着它可以在任何地方访问。

因此,在您上面的代码中,您可以使用该名称在任何地方访问objectX

anObject,另一方面,正确声明(作为参数),这意味着它的范围将被限制在Z函数内。

简而言之,您的代码编写方式,objectX 可以通过objectX 变量在任何地方访问,在函数Z 内,您可以将其引用为objectXanObject .


但是请注意,全局变量是一件坏事™,因为它们会使您很难弄清楚谁、何时以及为什么分配了哪个变量——正如您所注意到的。
虽然 Javascript 无法完全避免它们,但作为一项规则,您应该尽量保持变量的范围尽可能小(范围 = 在程序中可以访问该变量的位置)。

为此,我建议像 igorw 那样重构您的代码。

【讨论】:

    【解决方案5】:

    这里是jsfiddle的链接

    让我们看下面的例子:

    Person = function(name){
     this.name = name;
    }
    
    function x(){
         var john = new Person('john');
         return john;
    }
    
    function z(tempVar, anObject){
        var newObj = anObject;
        newObj.name = tempVar;
        return newObj;
    }
    
    myPerson = x();
    console.log(myPerson.name); //john
    console.log(z('peter', myPerson).name);  //peter
    console.log(myPerson.name); //peter
    

    您可以看到,即使您在 z 中创建了一个新对象,但是因为它们引用的是同一个对象,所以 myPerson 的 name 属性在 z() 被调用后也发生了变化。

    【讨论】:

    • 你想访问在函数 x 中创建的对象吗?
    • 是的。我明白你现在在说什么了。谢谢。
    • @Ben 如果您看一下@Clarence Fredericks 示例,它会介绍 JavaScript 如何使用“新”,并进一步说明 JavaScript 如何使用对象进行 OOP 等主题......非常好的东西