Search code examples
javascripthtmleval

Why does object.eval() work, square brackets return undefined?


I am attempting to write a script that takes the method (in the form of a string) from the first column of a table, and shows the output of said method in the third column of each row. ex. Row 1 column 1 of an html table contains .getFullYear(), so in column 3 I want to run (my Date object) now.getFullYear(). In the next row, I will run now.getMonth() and so on.

When I run eval("now."+method) it runs without issue, but I'm trying to avoid using eval(). When I run now[method] the output returns undefined. Why does eval() work but now[method] return something different?

```JavaScript`

const now = new Date();
//gets the full table data
const methodTable = document.querySelector("#methods-table");

function tableTimeData(table) {
    const tableLength = table.rows.length;
    for (let i = 1; i < tableLength; i++) { //iterate through each table row, skipping the header
        let row = table.rows[i];
        let method = row.cells[0].innerText;
        row.cells[2].innerText = eval("now." + method);
        //OR
        method = method.substr(1);
        row.cells[2].innerText = now[method];
    }
}

tableTimeData(methodTable);

HTML

   <table class="table" id="methods-table">
                <tr>
                    <th>Method Name</th>
                    <th>Method Description</th>
                    <th>Method Output</th>
                </tr>
                <tr>
                    <td class="text-info font-weight-bold">.getFullYear()</td>
                    <td>Returns the full 4 digit year.</td>
                    <td></td>
                </tr>
                <tr>
                    <td class="text-info font-weight-bold">.getMonth()</td>
                    <td>Returns the month as an integer (0-11).</td>
                    <td></td>
                </tr>
                <tr>
                    <td class="text-info font-weight-bold">.getDay()</td>
                    <td>Returns the day of the week as an integer (0-6).</td>
                    <td></td>
                </tr>
                <tr>
                    <td class="text-info font-weight-bold">.getHours()</td>
                    <td>Returns the hour as of creation.</td>
                    <td></td>
                </tr>
                <tr>
                    <td class="text-info font-weight-bold">.getMinutes()</td>
                    <td>Returns minute as of creation</td>
                    <td></td>
                </tr>
                <tr>
                    <td class="text-info font-weight-bold">.getSeconds()</td>
                    <td>Returns second as of creation</td>
                    <td></td>
                </tr>
                <tr>
                    <td class="text-info font-weight-bold">.getTime()</td>
                    <td>Returns the number of miliseconds passed since Jan. 1 1970. Used as a baseline to compare 2 dates.</td>
                    <td></td>
                </tr>
                <tr>
                    <td class="text-info font-weight-bold">.toDateString()</td>
                    <td>Returns a shortened date with day, month, date and year with day and month as names rather than integers.</td>
                    <td></td>
                </tr>
                <tr>
                    <td class="text-info font-weight-bold">.toTimeString()</td>
                    <td>Returns a shortened time of day with hour, minute second and time zone (always Greenwhich Mean Time as a standard).</td>
                    <td></td>
                </tr>
                <tr>
                    <td class="text-info font-weight-bold">.toLocaleString()</td>
                    <td>Returns a shortened time of day with hour, minute second and time zone (as your local time zone).</td>
                    <td></td>
                </tr>
            </table>

I expect the result of eval("now."+method) to be the same as now[method].


Solution

  • If method is .getFullYear(), then

    method = method.slice(1, -2);
    row.cells[2].innerText = now[method]();
    

    should work. You forgot to remove () from method