Why 'Unexpected “.”' when using || operato

2019-06-16 01:36发布

问题:

Getting Unexpected "." from jslint ( http://jslint.com/ ) on this code:

function test(foo) {
    "use strict";
    return (foo || "").replace("bar", "baz");
}

Why does jslint have a problem with the || operator to force an empty string so a replace can be performed without causing an error, in case foo is passed in as undefined?

This passes:

function test(foo) {
    "use strict";
    var xFoo = (foo || "");
    return xFoo.replace("bar", "baz");
}

I know it's opinion based and I can ignore it, etc... but trying to understand why chaining like this is frowned upon. Also know about eshint, but I'm not trying to get around this message, just want to understand why.

Seems like the first approach is more concise and cleaner since it doesn't need the extra variable (xFoo).

Both functions do exactly the same thing under all conditions.

回答1:

Using String() contructor removes error at jslint

function test(foo) {
    "use strict";
    return String(foo || "").replace("bar", "baz");
}

See also Distinction between string primitives and String objects , JSLint Help



回答2:

It may be because it believes (foo || "") will evaluate to a boolean expression, so something like false.replace() would not make sense. Even though, yes, in your case you get a variable or empty string instead.



回答3:

You could just make it two lines.

function test(foo) {
    "use strict";
    foo = foo || "";
    return foo.replace("bar", "baz");
}

There is no need to create a temporary xFoo variable. The foo parameter is a copy of the argument that was passed in since JavaScript does not support passing-by-reference.

It looks like what you are trying to do here is provide a default parameter. In that case I would make it crystal clear what you are doing by being even more explicit and type-checking it:

function test(foo) {
    "use strict";
    if (foo === undefined) {
      foo = "";
    }
    return foo.replace("bar", "baz");
}

Yes it is less succinct, but it will leave less room for the intention of the code to be misinterpreted by someone who reads it later. Explicitly checking the type also allows you to handle other potential problems.

function test(foo) {
    "use strict";
    if (foo === undefined) {
      foo = "";
    } else if (typeof foo !== 'string') {
      throw('foo must be a string');
    }
    return foo.replace("bar", "baz");
}

If you are using ES2015, you could also use a default parameter:

function test(foo = "") {
    "use strict";
    if (typeof foo !== 'string') {
      throw('foo must be a string');
    }
    return foo.replace("bar", "baz");
}

For pretty much any project I would suggest adding Babel to your build process so you can use default parameters and the many other useful features ES2015 adds to the language. Using Babel allows you to use them now without having to wait for all of the browsers to implement them.