I finally find the answers, I know nobody will write code totally same as I posted, using block directly, however, if you see this, javascript- Uncaught SyntaxError: Identifier * has already been declared, it's possible we may write code wrong if we don't have good understanding about scope in JS. I should mention the code should run in ES6 instead of ES5 strict mode, also mention it's running on Chrome which the browser supports the ES6, so sorry to confuse vikarpov.
Based on, http://www.ecma-international.org/ecma-262/6.0/#sec-additional-ecmascript-features-for-web-browsers, B.3.3, Block-Level Function Declarations Web Legacy Compatibility Semantics, In ES6, the function declaration in the block uses ES6 declaration semantics (like let or const), which does not allow redeclarations.
So the answer is 
{
  function test() {}
  test = 123
}
console.log(test)
console.log(typeof test)
will be 
var test
{
    let test = function test() {};
    window.test1 = test1
    test = 123;
}
console.log(test) //f test(){}
{
  function test1() {}
  test1 = 123
  function test1() {}
}
console.log(test1)
console.log(typeof test1)
will be
var test1
{
    let test1 = function test1() { }
    window.test1 = test1
    test1 = 123
    window.test1 = test1
}
console.log(test1) //123
{
  function test2() {}
  test2 = 123
  function test2() {}
  test2 = 345
}
console.log(test2)
will be
var test2
{
    let test2 = function test2() {}
    window.test2 = test2
    test2 = 123
    window.test2 = test2
    test2 = 345
}
console.log(test2)