MENU
- 01、概述
- 02、示例代码-1-函数的提升
- 03、示例代码-2-基本数据类型的提升
- 04、示例代码-3-函数提升优先级高于基本类型数据的提升
- 05、window对象
- 06、在一个函数中给一个未定义的变量赋值,变量会被挂载到window对象上
- 07、函数内的变量提升
- 08、函数形参的提升优先级低于函数
- 09、GO(global object)全局上下文
- 10、只有函数声明才会发生函数体一同提升
- 11、往外查找变量原则
- 12、如果自己身上有就不往外查找
- 13、AO与GO结合、并且注意函数是否被调用
- 14、是否往全局查找变量
- 15、预编译只管找变量和形参,不关注代码是否会被执行,所以变量提升与执行时是否进入某个判断无关
- 16、函数内变量提升并返回(return在后)
- 17、函数内变量提升并返回(return在前)
- 18、变量提升不会阻碍判断
- 19、多个相同函数声明的时候,最后声明的函数会覆盖先前所有提升过的函数
- 20、通过字面量声明的函数,如果在声明之前调用会报错,与定义变量的形式一样,声明会提前,但是赋值留在原地
- 21、形参、实参、函数表达式、函数声明
- 22、变量声明与函数声明的提升顺序,函数声明提升高于一切
- 23、变量声明的合并
- 24、预编译与逻辑判断无关
- 25、函数声明会提升,函数表达式不会提升,等同于定义变量
01、概述
JavaScript代码在执行之前首先经过预编译。预编译的过程中函数声明会被整体提升,变量只有声明被提升,赋值留在原地。
02、示例代码-1-函数的提升
precompileVariablePromotion();
// 预编译/变量提升
function precompileVariablePromotion() {
console.log('预编译/变量提升');
}
precompileVariablePromotion();
// 预编译/变量提升
此例中的两种执行顺序都能正确调用函数,说明函数发生了提升,且函数体的内容也一同被提升。
03、示例代码-2-基本数据类型的提升
console.log(a);
// undefined
var a;
console.log(a);
// undefined
a = 7;
console.log(a);
// 7
此例中的a在打印时都没有报错,所以说明了a被提升了,只是没有赋值,所以前两个打印的值为undefined,第三个打印才是赋值,也说明了赋值留在原地。
04、示例代码-3-函数提升优先级高于基本类型数据的提升
console.log(precompileVariablePromotion);
// ƒ precompileVariablePromotion(precompileVariablePromotion) {
// var precompileVariablePromotion = 7;
// var precompileVariablePromotion = function () { };
// }
var precompileVariablePromotion = 3;
function precompileVariablePromotion(precompileVariablePromotion) {
var precompileVariablePromotion = 7;
var precompileVariablePromotion = function () { };
}
var precompileVariablePromotion = 5;
此例中函数发生了提升,并且函数体同时被提升。因为函数提升的优先级高于基本类型数据提升,所以函数提升会覆盖掉所有同名的基本类型数据提升。
05、window对象
var a = 1;
// 如果给一个为声明的变量赋值
// 那么此变量会被挂载到window对象上
b = 2;
console.log(window.a, window.b);
// 1 2
window.a = 7;
window.b = 6;
console.log(window.a, window.b);
// 7 6
此例中的两种方式是一样的效果,都是把值挂载到window对象上。
06、在一个函数中给一个未定义的变量赋值,变量会被挂载到window对象上
function precompileVariablePromotion() {
var a = b = 7;
// 此写法等同于
// b = 7;
// var a = b;
// 且从右往左执行
// 在一个函数中给一个未定义的变量赋值,
// 此变量会被挂载到window对象上
}
precompileVariablePromotion();
// console.log(a);
// Uncaught ReferenceError: a is not defined
console.log(window.b, b);
// 7 7
// 此处的b被挂载到window上了
07、函数内的变量提升
function precompileVariablePromotion(params) {
console.log(params);
// 因为函数提升的优先级最高,
// 所以此处打印的是函数表达式
// ƒ params() { }
var params = 7;
console.log(params);
// 因为到此处时之前的变量提升已经结束,
// 已经到了赋值阶段
// 所以打印了7
// 7
function params() { };
// 当代码运行到此处时,
// 函数已经提升过了
// 所以不会再做任何操作
// 因此下一个打印的值依然是7
console.log(params);
// 7
var b = function () { };
console.log(b);
// ƒ () { }
function c() { };
// 函数c只是起到迷惑的作用
}
precompileVariablePromotion(3);
08、函数形参的提升优先级低于函数
function precompileVariablePromotion(a, b) {
console.log(a);
// 3
c = 7;
var c;
a = 5;
b = 6;
console.log(b);
// 6
function b() { };
// 在预编译时b已经被提升,
// 所以在运行时不会再做任何操作
// 也就是说 b = 6; 能正常赋值
// 所以两个打印都是 6
function d() { };
console.log(b);
// 6
// 如果打开此处的注释
// 那么第一打印就是
// ƒ a() { }
// 这里进步一步说明了
// 函数提升的优先级高于形参提升的优先级
// function a() { };
}
precompileVariablePromotion(3);
09、GO(global object)全局上下文
console.log(precompileVariablePromotion);
// ƒ precompileVariablePromotion() {
// console.log(7);
// }
var precompileVariablePromotion = 1;
function precompileVariablePromotion() {
console.log(7);
}
console.log(precompileVariablePromotion);
// 1
// 在预编译时,函数声明已被提升
// 之后声明了变量,且给变量赋值为1
// 所以在函数后面打印到的就是1
10、只有函数声明才会发生函数体一同提升
console.log(a);
// ƒ a() { }
console.log(b);
// undefined
// 因为b就是个普通的变量
// 在此处b发生了变量提升
// 但是没有值
// 所以是undefined
// 只有函数声明才会发生变量提升和函数体一起提升
function a() { };
var b = function () { };
11、往外查找变量原则
function precompileVariablePromotion() {
var a = b = 7;
// 此处的b被挂载到全局window上
console.log(a);
// 7
console.log(b);
// 7
console.log(window.b);
// 7
}
precompileVariablePromotion();
// console.log(a);
// Uncaught ReferenceError: a is not defined
console.log(b);
// 7
12、如果自己身上有就不往外查找
var b = 2;
function precompileVariablePromotion() {
var a = 3,
b = 7;
console.log(a);
// 3
console.log(b);
// 7
// 因为函数内部有b变量,
// 所以不会往外查找
console.log(window.b);
// 2
}
precompileVariablePromotion();
console.log(b);
// 2
13、AO与GO结合、并且注意函数是否被调用
var b = 3;
console.log(a);
// ƒ a(a) {
// console.log(a);
// var a = 2;
// console.log(a);
// function a() {
// var b = 5;
// console.log(b);
// }
// }
function a(a) {
console.log(a);
// ƒ a() {
// var b = 5;
// console.log(b);
// }
var a = 2;
console.log(a);
// 2
function a() {
var b = 5;
console.log(b);
}
}
a(1);
14、是否往全局查找变量
a = 1;
function test() {
console.log(a);
// undefined
// 函数内发生了变量提升
// 因为 var a = 3;
// 所以不会往全局找
a = 2;
console.log(a);
// 2
var a = 3;
console.log(a);
// 3
}
test();
var a;
15、预编译只管找变量和形参,不关注代码是否会被执行,所以变量提升与执行时是否进入某个判断无关
function test() {
console.log(b);
// undefined
// 预编译只管找变量和形参,
// 不关注代码是否会被执行
// 所以变量提升与是否进入某个判断无关
console.log(a);
// undefined
// 此处的a用的是GO(全局)里面的变量
if(a){
var b = 2;
}
c = 3;
console.log(c);
// 3
console.log(b);
// undefined
}
var a;
test();
a = 1;
console.log(a);
// 1
16、函数内变量提升并返回(return在后)
function test() {
a = 1;
function a() { };
var a = 2;
return a;
}
console.log(test());
// 2
17、函数内变量提升并返回(return在前)
function test() {
return a;
a = 1;
function a() { };
var a = 2;
}
console.log(test());
// ƒ a() { }
18、变量提升不会阻碍判断
a = 1;
function test(e) {
function e() { };
arguments[0] = 2;
console.log(e);
// 2
console.log(a);
// a发生了变量提升
// 但是还没有赋值
// 所以进不了判断
if (a) {
var b = 3;
}
var c;
a = 4;
var a;
console.log(b);
// undefined
// b发生了变量提升
// 因为预编译不管是否会进入判断
// 都会发生变量提升
f = 5;
console.log(c);
// undefined
console.log(a);
// 4
}
var a;
test(1);
console.log(f);
// 5
console.log(a);
// 1
19、多个相同函数声明的时候,最后声明的函数会覆盖先前所有提升过的函数
fn();
// 2
function fn() {
console.log('1');
}
function fn() {
console.log('2');
}
20、通过字面量声明的函数,如果在声明之前调用会报错,与定义变量的形式一样,声明会提前,但是赋值留在原地
fn();
// Uncaught TypeError: fn is not a function
var fn = function () {
console.log('fn');
}
21、形参、实参、函数表达式、函数声明
function fn(a) {
console.log(a);
// ƒ a() {}
var a = 7;
console.log(a);
// 7
function a() {};
console.log(a);
// 7
var b = function() {};
console.log(b);
// ƒ () {}
function d() {};
var d = a;
console.log(d);
// 7
}
fn(1);
22、变量声明与函数声明的提升顺序,函数声明提升高于一切
console.log(a);
// ƒ a() {
// return 3;
// }
function a() {
return 3;
}
var a = 7;
console.log(a);
// 7
23、变量声明的合并
console.log(a);
// ƒ a() {
// return 3;
// }
var a = 3;
function a() {
return 3;
}
var a = 7;
console.log(a);
// 7
24、预编译与逻辑判断无关
函数内部有自己的变量就不会向外部查找,且在预编译时所以的变量都要经过提升这个过程,不管判断和逻辑。
var a = 4;
(function () {
// 'undefined'不等undefined
if (typeof a == undefined) {
var a = 5;
console.log(a);
} else {
console.log(a);
// undefined
}
})();
25、函数声明会提升,函数表达式不会提升,等同于定义变量
foo();
// foo
bar();
// Uncaught TypeError: bar is not a function
function foo() {
console.log('foo');
}
var bar = function() {
console.log('bar');
}