Following test-driven development  can compensate for broad gaps in knowledge of the language being used.
For example, situations where values are passed instead of pointers or some tricky
break statement can all be accounted for in the test suite. If the code is modular enough and the tests are fairly exhaustive, the actual implementation doesn’t really matter - as long as the contract between the method and the tests is respected, you don’t need to know how it makes anything happen.
One caveat is lower-level optimizations; those will still require a deeper understanding of the language in question in order to implement them correctly.