You are using a function expression:
FunctionExpression :
function Identifieropt ( FormalParameterListopt
) { FunctionBody }
So b = function c() { ... }; is perfectly valid, strict mode or otherwise. What happens to c is another question. According to the specs:
The production
FunctionExpression : function Identifier (
FormalParameterListopt ) { FunctionBody }
is evaluated as follows:
[...]
3. Call the CreateImmutableBinding concrete method of envRec
passing the String value of Identifier as the argument.
4. Let closure be the result of creating a new Function object
as specified in 13.2 [...]
5. Call the InitializeImmutableBinding concrete method of envRec
passing the String value of Identifier and closure as the arguments.
[...]
NOTE
The Identifier in a FunctionExpression can be referenced from
inside the FunctionExpression's FunctionBody to allow the function to
call itself recursively. However, unlike in a FunctionDeclaration, the
Identifier in a FunctionExpression cannot be referenced from and does
not affect the scope enclosing the FunctionExpression.
So:
c is visible inside the function but not outside it
c cannot be overwritten from inside the function (an "immutable" binding)
Meanwhile, from the code below I got the right "3".
function ff() {
This is a function declaration; different (and more obvious) rules apply here.