文章目录
  1. 1. 函数声明(funDeclaration)
  2. 2. 函数表达式(funExpression)
    1. 2.1. demo1
    2. 2.2. demo2
      1. 2.2.1. 主流浏览器解析,ie11+
      2. 2.2.2. ie9,ie10
      3. 2.2.3. ie8
    3. 2.3. 结论
      1. 2.3.0.1. 参考

函数声明(funDeclaration)

无论在哪儿定义函数,只要是外层函数并且满足不被包裹,就都可以进行全局范围的调用

1
function foo() {}

在函数体内部的函数声明无法提升到全局,只能提升到函数体内顶部(块级作用域空间)

1
2
3
4
5
6
7
8
9
function test() {
console.log(1);

function test2() {
console.log(2);
}
}
test(); // 1
test2(); // Uncaught ReferenceError: test2 is not defined

函数体内部执行:

1
2
3
4
5
6
7
function test() {
test2();
function test2() {
console.log(2);
}
}
test(); // 2

在外部要想访问函数内部申明的函数,需要先return出来:

1
2
3
4
5
6
7
8
9
10
11
function test() {
console.log(1);

function test2() {
console.log(2);
}
return {
test2: test2
};
}
test().test2(); // 2

函数表达式(funExpression)

函数表达式需要等到表达式赋值 完成 才可以

换言之使用var来声明函数,就会涉及到变量的声明提升,先拿出变量名定义为 undefined,再随着逻辑顺序进行赋值先定义,后使用

1
var foo = function () { }

demo1

1
2
3
4
5
6
7
8
9
10
Toast(); // hello world

showToast(); // shwoToast is not a function

var showToast = function() {
console.log("123");
};
function Toast() {
console.log("hello world");
}

在这里只需要把showToast提前就好了

demo2

主流浏览器解析,ie11+

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var sayHello;
console.log(typeof sayHey); //=>undefined
console.log(typeof sayHo); //=>undefined
if (true) {
function sayHey() {
console.log("sayHey");
}
sayHello = function sayHo() {
console.log("sayHello");
};
} else {
function sayHey() {
console.log("sayHey2");
}
sayHello = function sayHo() {
console.log("sayHello2");
};
}
sayHey(); // => sayHey
sayHello(); // => sayHello

在花括号里面声明的函数在进行预解析时只会提升函数名,不会提升函数体,所以不管 if 条件是否为真,函数体都不会提升,永远是 undefined,接下来随着 if 条件判断进行解析赋值,当然是走 ture 方法。

ie9,ie10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var sayHello;
console.log(typeof sayHey); //=>function
console.log(typeof sayHo); //=>undefined
if (true) {
function sayHey() {
console.log("sayHey");
}
sayHello = function sayHo() {
console.log("sayHello");
};
} else {
function sayHey() {
console.log("sayHey2");
}
sayHello = function sayHo() {
console.log("sayHello2");
};
}
sayHey(); // => sayHey2
sayHello(); // => sayHello

在这里的 ie 将所有的函数声明进行了提升,从而由sayHey2替代了sayHey,函数表达式的在顺着条件判断进行了定义,执行为true的情况,进行赋值解析。

ie8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var sayHello;
console.log(typeof sayHey); //=>function
console.log(typeof sayHello); //=>function
if (true) {
function sayHey() {
console.log("sayHey");
}
sayHello = function sayHo() {
console.log("sayHello");
};
} else {
function sayHey() {
console.log("sayHey2");
}
sayHello = function sayHo() {
console.log("sayHello2");
};
}
sayHey(); // => sayHey2
sayHello(); // => sayHello

ie8 在这里处理的比较奇葩,正常的函数申明提升,但是却也将条件判断为假的情况进行了提升,我们看到typeof (sayHello)=>function

结论

由于函数声明提升的差异,想要在条件判断中定义不同的函数方法,应该采用定义函数表达式的方法,这样就在各个浏览器中拿到相同的函数方法,得到相同的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
var sayHello;
console.log(typeof sayHey); //=>undefined ie8以下解析为function
console.log(typeof sayHo); //=>undefined
if (true) {
var sayHey = function sayHey() {
console.log("sayHey");
};
} else {
var sayHey = function sayHey() {
console.log("sayHey2");
};
}
sayHey(); // => sayHey
参考
文章目录
  1. 1. 函数声明(funDeclaration)
  2. 2. 函数表达式(funExpression)
    1. 2.1. demo1
    2. 2.2. demo2
      1. 2.2.1. 主流浏览器解析,ie11+
      2. 2.2.2. ie9,ie10
      3. 2.2.3. ie8
    3. 2.3. 结论
      1. 2.3.0.1. 参考