If you notice your code, at line 5 this function is calling itself, this is called recursion, read more about it on wikipedia
Lets comeback to your code and dry run it to see how it works. lets give each line a number so we can refer it
1.function fac(n) {
2. if (n == 0)
3. return 1;
4. else
5. return fac(n - 1) * n;
6.}
7.console.log(fac(4));
your input value is 4 for first call lets call it call A.
for value 4 if condition at line 1 will return false so it would go to line 5 which again calls
fac(3) * 4;
now your function call A is paused here and makes a call B with value 3. Result of call A is yet to be evaluated.
Now with value 3 this if condition at line 2 will return false again and code at line 5 will execute like above; i.e.
fac(2) * 3;
call B paused here and there will be call C with input 2 of the same function.
on call C you code will return false against if condition at line 2 so it will make call D with input 1. i.e.
fac(1) * 2
For call D if condition at line 2 will return true and your function will return 1 so the call D gets evaluated at with value 1. now replace each fac(n) from bottom to top and keep on evaluating each call.
result of call D => 1
result of call C => fac(1) * 2 => 1 * 2 => 2
result of call B => fac(2) * 3 => 2 * 3 => 6
result of call A => fac(3) * 4 => 6 * 4 => 24
I hope you will be able to understand how it really works, important point in recursion is the stop condition which you code has it at line 2.
Above result can also be produced by using loops but using recursion is more fun.
Happy Coding :)