Fork me on GitHub

JS-变量对象

变量对象

变量对象 Variable Object

函数变量对象的创建过程

  1. 建立arguments对象:检查当前上下文的函数参数,建立该对象下的属性和属性值。
  2. 检查当前上下文的函数声明,指的是function关键字声明的函数,在变量对象中以函数名建立一个属性,属性值为指向该函数的所在内存地址的引用。
  3. 检查当前上下文中的变量声明,在变量对象中以变量名建立一个属性,属性值为undefined

如果变量与函数同名,则在这个阶段,以函数值为准

1
2
3
console.log(foo); // function foo
function foo() { console.log('function foo') }
var foo = 20;

函数参数与变量同名,参数为准

1
2
3
4
5
function foo(a){
console.log(a);//20
a=10;
}
foo(20)

函数参数与内部函数同名,内部函数为准

1
2
3
4
5
function foo(a){
console.log(a); //f a(){}
function a(){}
}
foo(20)

具体过程

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

var a = 1;
function foo() {
return 2;
}
}

test();
  1. 创建
    创建变量对象
    未进入执行阶段之前,变量对象中的属性都不能访问!但是进入执行阶段之后,变量对象转变为了活动对象,里面的属性都能被访问了,然后开始进行执行阶段的操作。

  2. 执行阶段
    AO:活动对象
    创建变量对象
    实际执行过程

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function test() {
    function foo() {
    return 2;
    }
    var a;
    console.log(a);
    console.log(foo());
    a = 1;
    }

    test();

全局上下文变量对象

浏览器,全局对象为Window

1
2
3
4
5
windowEC={
VO:Window,
scopeChain:{},
this:Window
}

变量对象和this都指向Window对象
全局上下文的生命周期,与程序的生命周期一致,只要程序运行不结束,比如关掉浏览器窗口,全局上下文就会一直存在。其他所有的上下文环境,都能直接访问全局上下文的属性。

let/const

let/const 声明的变量,是否还会变量提升?
let/const 声明的变量,仍然会提前被收集到变量对象中,但和var不同的是,let/const定义的变量,不会在这个时候给他赋值undefined
因为存在暂时性死区,所以不能再声明前使用。

变量提升

编译时和运行时

  • 编译时:var 和 function 声明的变量和函数提升
  • 运行时:变量初始化

什么是变量提升

将变量声明及函数声明提升至当前作用域的顶端。

为什么会存在变量提升

提升存在的根本原因就是为了解决函数间互相调用的情况

  • var 声明的提升
    只提升声明,未赋值前使用是undefined
    var 声明的变量只存在全局作用域和函数作用域

例一

1
2
3
console.log(a);
var a=10;
console.log(a);

预编译

1
2
3
4
var a;
console.log(a);//undefined
a=10;
console.log(a);//10

例二
如果当前作用域声明了多个同名变量,同一个标识符会被提升到顶部,赋值操作顺序执行。

1
2
3
var a = 10
var a
console.log(a)

预编译

1
2
3
var a
a = 10
console.log(a)//10
  • 函数声明提升

    • 如果函数声明方式跟变量声明方式一样,则提升方式也是一样的
    1
    2
    3
    4
    5
    console.log(fun);//undefined
    var fun=function(){
    console.log(1);
    }
    fun();//1
    • 使用function声明
      会把声明和赋值全部提升到作用域顶部
    1
    2
    3
    4
    fun();//1
    function fun(){
    console.log(1);
    }

例三

1
2
3
4
5
6
7
8
9
10
11
12
13
function test(arg) {
console.log(arg);
//ƒ arg(){
//console.log('hello world');
//}
var arg = 'hello';

function arg() {
console.log('hello world');
}
console.log(arg) //hello
}
test('hi')

阿里面试题

考点:变量提升,作用域,继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function Foo() {
getName = function () {
console.log(1);
};
return this;
}
Foo.getName = function () {
console.log(2);
};
Foo.prototype.getName = function () {
console.log(3);
};
var getName = function () {
console.log(4);
};
function getName() {
console.log(5);
}
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
//2 4 1 1 2 3 3

运算优先级

-------------本文结束感谢阅读-------------