So, two easy ways to handle this. One involves manipulating the order of evaluation, and the other involves using a fitting function that returns a functional object.
First:
f[x_] := Evaluate[Fit[data, {x^4, x^3, x^2, x, 1}, x]];
This evaluates the Fit before setting f[x_]:= to it.
Secondly:
f = LinearModelFit[data, {x^4, x^3, x^2, x}, x]
LinearModelFit returns a model object, which can be called as a function, but has a bunch of other useful properties such as R-squared values and an ANOVA table. These can be examined by calling f["Properties"] and the various labels that shows, such as f["RSquared"]. Note that LinearModelFit, by default, includes a constant term automatically. This can be disabled by setting IncludeConstantBasis -> False.
You may also be interested in knowing that NonlinearModelFit exists and has similar properties, if you end up having to deal with more complicated models.
It has also been pointed out by @HenrikSchumacher and @SjoerdSmit that this is a case where using Set instead of SetDelayed to define the function has the expected and desired result:
f[x_] = Fit[data, {x^4, x^3, x^2, x, 1}, x];
This is actually functionally the same as using Evaluate in the SetDelayed expression. I'd recommend checking this answer for further reading regarding := and =.
fit[x_]:=Evaluate @ Fit[...– Kuba Sep 17 '18 at 15:59