The peer comment about static typing is correct, but there's more, err, flavor to be enjoyed in the challenges of JITing JS. Here's some deopt scenarios to keep you up at night.
To whet your appetite, what happens if you redefine Math.round? Java prohibits this for obvious reasons, but a JS joker may write:
Math.round = () => Infinity;
JS engines really do inline Math.round, and must be prepared for this nonsense.
It gets worse. Maybe you check for a property which is usually not found:
if (!val.uuid)
val.uuid = uuidgen();
Hidden classes can almost reduce this to a pointer comparison. But what if someone adds a uuid property on Object.prototype? Every check is busted! v8 handles this with "validity cells", and it's ugly, requiring that every object know about every object which "inherits" from it.
Now if you are a monster you may choose to write:
Object.defineProperty(Array.prototype, "42", {value: "lol"});
console.log([][42]); // yes it prints "lol"
Every array gets a default value for 42. Think about how you would JIT numeric code in such an environment...