为什么这个函数表现得很奇怪

时间:2016-08-31 04:53:22

标签: javascript

我有以下JavaScript,如下所示

function getExpiryDate(contract) {
    var expiryDay;
    var contractType;
    var today = new moment();
    var today1 = new moment();

    var x = myFunction(4, 3);
    var abc =3;
    var xyz= 4;
    var c = myFunction(abc, xyz);

    console.log("abc is: "+abc);
    console.log("xyz is: "+xyz);
    console.log(today1);

    expiryDay = getlastDayofMonth('Thursday',today1);

    console.log(today1); /* Why has the value of today changed? */
}

function getlastDayofMonth(dayName,date1) {

    var endDate = date1.endOf('month');
    var lastDayOfMonth =  endDate.format('dddd');
    var weekDayToFind = moment().day(dayName).weekday(); //change to searched day name

    var searchDate = endDate; //now or change to any date

    while (searchDate.weekday() !== weekDayToFind)
    { 
        searchDate.subtract(1, 'days'); 
    }

    return searchDate;
}

function myFunction(a, b) {
    return a * b;                // Function returns the product of a and b
}

当我执行时,我得到以下输出。

expirydate.js:11 abc is: 3
expirydate.js:12 xyz is: 4
expirydate.js:13 Moment { _d: Wed Aug 31 2016 10:21:04 GMT+0530 }
expirydate.js:15 Moment { _d: Thu Aug 25 2016 23:59:59 GMT+0530 }

我完全混淆了为什么今天的值1在函数中使用时会发生变化。

2 个答案:

答案 0 :(得分:4)

因为在JS中,对象是通过引用而不是通过值传递的。这意味着你正在处理同一个对象。

为了防止这种情况,你必须将函数中的date1值克隆到一个变量,该变量的范围仅限于函数

答案 1 :(得分:2)

这种情况正在发生,因为Moment是以可变的代码风格编写的。这是相当令人惊讶的行为。在阅读了几次代码后,在查看Moment文档之前,我找不到任何明显的问题。

.endOf()方法会改变日期,也就是更改您调用它的时刻对象的日期:

  

通过将原始时刻设置为单位时间的结尾来突变原始时刻。

所以当你在这里调用那个方法时:

var endDate = date1.endOf('month');

它正在改变date1,这意味着它会修改date1并更改其时间。实际上,看起来几乎所有时刻的方法都会改变当下的对象。关于为什么API设计不佳,有一个discussion on Github

在解决您的具体问题方面,这是个人风格偏好。我认为在将对象传递给函数之前强制用户克隆对象是不可取的。所以我会克隆函数内部传递的那一刻:

function getlastDayofMonth(dayName,date1) {

    var endDate = date1.clone().endOf('month');