Unexpected '.' from wrapped expression to chain

孤街醉人 提交于 2019-12-10 15:34:24

问题


I have this method that is calculating a total, and part of it is giving a warning in JS Lint. We're trying to get cleaner JS Lint inspections at work, so I want to see if there's a rational way to get around this that I'm not thinking of.

calculateTotal = function() {
    var hours = parseFloat($hours.val());
    var rate = parserFloat($rate.val());
    var total = '';

    if (!isNaN(hours) && !isNaN(rate)) {
        // This throws the error.
        total = (rate * hours).toFixed(2);
    }

    $total.val(total);
}

I can avoid the message if I do the following:

total = rate * hours;
total = total.toFixed(2);

It's a little too verbose for me to just jump at it, but it may be the best bet.

I checked out this question, and considered doing Number(rate * hours).toFixed(2), but that's (marginally) less performant, plus it would be a bad precedent to start with all of the warnings about using String() as stated in response to the accepted answer there.

This could be moot if my above attempt is the best way to get JS Lint to stop complaining, but I would like to hear from other people.


回答1:


TL;DR

JSLint is going to force you to move the toFixed() from behind of the parentheses. I'd suggest the least annoying place to move it is in the $total.val(total) assignment.

This lints as-is on JSLint.com:

/*jslint white:true, browser:true */
/*global $hours, $rate, $total */

var calculateTotal = function() {
    "use strict";
    var hours = parseFloat($hours.val());
    var rate = parseFloat($rate.val());
    var total;

    if (!isNaN(hours) && !isNaN(rate)) {
        // This throws the error.
        total = rate * hours;
    }

    $total.val(total.toFixed(2));  // moved `toFixed` to here
};

A little longer...

I tried it against the most recent version of JSLint, and it's borking at left_check in JSLint's code, here:

function left_check(left, right) {

// Warn if the left is not one of these:
//      e.b
//      e[b]
//      e()
//      identifier

    var id = left.id;
    if (
        !left.identifier &&
        (
            left.arity !== "binary" ||
            (id !== "." && id !== "(" && id !== "[")
        )
    ) {
        warn("unexpected_a", right);
        return false;
    }
    return true;
}

left is essentially (rate & hours) and right is . with toFixed the next token in this case.

As dangerous as it is to assume code function from comments, I think the comments tell us where JSLint is coming from -- It wants methods called only on objects, not on operations, including type coercions that often occur inside of them. It pretty much has to let you make "fluent" calls, where you chain methods, and the only valid things that can have method calls are...

  • an object: e
  • A property of an object: e.b
  • A property in a collection: e[key]
  • The return value of a function: e()

Just to double check, since your construction used to work in "old JSLint" (the last version before JSLint for ES6), I asked Douglas Crockford. He's pretty terse, but he did confirm JSLint is working as intended.

Sorry I can't be more help there. I think there are places where (someExpression).someMethod() is expedient, but understand where JSLint's coming from too. If you're going to have the potential for type coercion, coerce explicitly.

Interesting question; thanks for asking.



来源:https://stackoverflow.com/questions/36581877/unexpected-from-wrapped-expression-to-chain

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!