为什么返回对象的JavaScript函数通过引用(对其参数)来做??

时间:2015-09-30 04:01:50

标签: javascript pass-by-reference

我有一个函数返回一个对象,其中一个属性是作为参数(参数)传递给它的日期对象的值。

当从循环中调用此函数时,改变发送到它的日期参数并将所有返回的对象添加到数组中 - 我注意到数组中的所有对象都以相同的值结束对于日期对象 - 这是循环内日期的最终值。

为了演示,我有一个函数(theFunction),它返回字符串表示以及date参数本身作为返回对象的两个属性。

从另一个函数(theLoop)调用此函数,该函数使用循环内的不同日期值调用theFunction并将函数调用的结果存储到数组中。

var theFunction = function (inputDate) {
    /* The string representation and the date itself as properties on the returned object */
    return {
        string: inputDate.toLocaleString(),
        original: inputDate
    };
};

var theLoop = function (startDate) {
    // declare an array for the output
    var dates = [];

    for (var minute = 0; minute < 1440; minute = minute + 30) {
        var newHour = minute % 60,
            newMinute = minute - newHour * 60;
        // loop and increment the time by a half-hour starting from midnight until minutes < 1440
        startDate.setHours(newHour, newMinute);
        // record the output from theFunction into the array
        dates.push(theFunction(startDate));
    }
    // return the array
    return dates;
};

// get the array
var datesArray = theLoop(new Date());

// console.log the array
console.log(datesArray);

请参阅this fiddle以运行上述代码。

问题1:为什么从名为theFunction的函数中返回的对象持有对theLoop中循环内递增的日期变量的引用?

问题2:如何更改theFunction以便它返回传递给它的日期的副本?

3 个答案:

答案 0 :(得分:2)

问题1 :Javascript中的DateObject;在Javascript Object中,Function指针,因此,对象值只是一个指针。当您将对象(或函数)作为参数传递(或将对象值分配给另一个变量)时,您传递(或分配)指向内存中“真实”对象的指针。在这种情况下:

//get the array
var datesArray = theLoop(new Date());

您通过new Date()作为参数调用theLoop,您刚刚传递了一个指针,您没有传递该对象的新副本。因此,修改“几个”日期只是通过其指针的几个副本修改一个内存位置中的一个日期。

问题2 :要解决此问题,只需在theLoop中添加一点:

var theLoop = function (startDate) { // 'startDate' should be renamed, but I still use this for ease of explain.
  ...
  for (...) {
    startDate = new Date(startDate); // HERE!!
    ...
  }
  return dates;
}

因为new Date(startDate)会创建原始日期的新副本。有关更多详细信息:Javascript中的Date包含一个名为timestamp的无符号整数;在这种情况下,new Date(startDate)完全等同于new Date(parseInt(startDate))new Date(startDate.valueOf())

重要:同样,Javascript参数不是通过引用传递的,这是错误的,它们总是通过值传递任何类型的值。使用对象(或函数),它们也不会通过引用传递!相反,它们是指针,让我们说指针(对象)是通过值传递的。

此外,现在您可能知道运算符new实际意味着什么。我认为,就像C ++一样,它意味着“创建指向已分配内存区域的指针”。

答案 1 :(得分:1)

  1. 因为每个对象仍然引用相同的startDate对象。因此,当startDate发生更改时,每个对象都会受到该更改的影响。

  2. 将您的循环更改为此

    var theLoop = function (startDate) {
    // declare an array for the output
    var dates = [];
    
    for (var minute = 0; minute < 1440; minute = minute + 30) {
        var newHour = minute % 60,
            newMinute = minute - newHour * 60;
        // loop and increment the time by a half-hour starting from midnight until minutes < 1440
        startDate.setHours(newHour, newMinute);
        var newDate = new Date(startDate.getTime());
        // record the output from theFunction into the array
        dates.push(theFunction(newDate));
    }
    // return the array
    return dates;
    };
    

答案 2 :(得分:1)

您有一个Date对象(startDate),您可以使用setHours进行修改,并在每次迭代中将引用传递给theFunction。

要解决此问题,请从inputDateupdated fiddle)创建新日期:

var theFunction = function (inputDate) {
    /* The string representation and the date itself as properties on the returned object */

    var inputDateClone = new Date(inputDate.getTime()); // the cloned date

    return {
        string: inputDateClone.toLocaleString(),
        original: inputDateClone
    };
};