简体   繁体   中英

Why is this function behaving weirdly

I have the following JavaScript as below

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
}

When I execute I get the following output.

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 }

I am totally confused on why the value of today1 changes when it is used in the function.

Because in JS, objects are passing by reference and not by value. It means you are working on the same object.

To prevent this you have to clone date1 value in the function into a variable with a scope restricted to the function

This is happening because Moment is written in a mutable style of code. It's fairly surprising behavior. After reading through your code a few times I couldn't find any obvious problem until I looked at the Moment documentation.

The .endOf() method mutates the date, aka changes the date of the moment object you call it on:

Mutates the original moment by setting it to the end of a unit of time.

So when you call that method here:

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

It's mutating date1 , meaning it modifies date1 in place and changes its time. In fact, it looks like almost all of moment's methods mutate the moment object. There's a discussion on Github about why the API is designed poorly.

In terms of solving your specific problem, it's a personal style preference. I think it's undesirable to force the user to clone an object before passing it to a function. So I would clone the moment passed in inside the function:

function getlastDayofMonth(dayName,date1) {

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM