在JavaScript中,变量和函数的声明提升是一种特性,它允许我们在使用之前声明变量和函数。在本文中,我们将探讨变量和函数声明的提升规则,并介绍预编译的概念。
首先,我们来了解一下变量声明提升。在JavaScript中,使用var关键字声明的变量会存在声明提升
var 声明提升
a=0
var a
console.log(a)// a=0
//代码等于下面的
var a
a=0
console.log(a)// a=0
在这上面就展示了,var关键字的声明提升,但是const,let不存在声明提升,这意味着变量的声明会被提升到当前作用域的顶部,无论声明语句出现在哪里,变量都可以在声明之前被访问。但需要注意的是,只有声明被提升,而不包括赋值。变量的赋值操作仍然会按照代码的执行顺序进行。
函数的声明提升
foo()
function foo() {
console.log('hello');
}
// 代码等于
function foo() {
console.log('hello');
}
foo()
但是我们要注意的是与变量声明不同,函数声明整体会被提升到当前作用域的顶部。这意味着我们可以在函数声明之前调用该函数,而不会引发错误。函数声明提升的优先级高于变量声明提升。
在理解声明提升的基础上,我们来介绍一下预编译的概念。
预编译
预编译是JavaScript代码执行前的一个阶段,它会创建变量对象(Variable Object)或活动对象(Action Object),并对变量和函数进行初始化。预编译分为两种情况:函数体内的预编译和全局预编译。
在函数体内的预编译
- 创建函数的AO对象(Action Object)
- 找形参和变量声明,将形参和变量声明作为AO的属性名,值赋予undefined
- 将形参和实参统一
- 在函数体内找函数声明,将函数名作为AO对象的属性名,值赋予函数体
function fn(a) {
console.log(a); // function a() {}
var a = 123
console.log(a); // 123
function a() { }
console.log(a); // 123
var b = function () { } // 函数表达式
console.log(b); // function() {}
function d() { }
var d = a
console.log(d); // 123
}
// AO = {
// a: undefined 1 function a() {} 123,
// b: undefined function() {},
// d: undefined function d() {} 123,
// }
fn(1)
全局的预编译
- 创建GO对象 (Global Object)
- 找变量声明,将变量明作为GO的属性名,值赋予undefined
- 在全局找函数声明,将函数名作为GO对象的属性名,值赋予函数体
// GO = {
// global: undefined 100,
// fn: function fn() {xxx}
// }
var global = 100
function fn() {
console.log(global);
}
// AO = {
// }
fn()
接下来我们来一个负责的代码您能打印出他们嘛
// GO = {
// global: undefined 100,
// fn: function fn() {}
// }
global = 100
function fn() {
console.log(global); // undefined
global = 200
console.log(global); // 200
var global = 300
}
// AO = {
// global: undefined 200 300
// }
fn()
var global;
总结一下,JavaScript中的声明提升是一种特性,可以在声明之前使用变量和调用函数。变量声明会被提升到当前作用域的顶部,而函数声明整体会被提升到当前作用域的顶部。预编译是JavaScript代码执行前的阶段,它会对变量和函数进行初始化。函数体内的预编译和全局预编译分别创建了函数的活动对象和全局对象。
希望本文对你理解JavaScript中的声明提升和预编译过程有所帮助!