It exists (npm shrinkwrap [1]), but it's not enabled by default, and it has some warts, such as non-deterministic sorting of entries.
There's a third-party tool [2] that is supposed to solve many of the issues, but I haven't tried it.
Of course, if you do this, there's a decent chance that if you try installing it again in 6 months, your shrinkwrapped version of at least one of the dependencies won't be available any more...
Biggest wart I've encountered is I've got a package that installs fsevents (OSX-only) as one of its optional dependencies. When I shrinkwrap and attempt to install on a Linux server, that optional dependency is treated as a required one, and it can't install. I have to manually zap it from the JSON. :-/
One wonders, why shouldn't it be 'npm lock'... I'm not that into plastic packaging, and not a native speaker, so shrinkwrap gives me as much clue about what the command does as blinktap, or pricklywarp.
There's a third-party tool [2] that is supposed to solve many of the issues, but I haven't tried it.
Of course, if you do this, there's a decent chance that if you try installing it again in 6 months, your shrinkwrapped version of at least one of the dependencies won't be available any more...
[1]: https://docs.npmjs.com/cli/shrinkwrap [2]: https://github.com/uber/npm-shrinkwrap