JavaScript学习记录5

1 背景

最近在学习JavaScript,今天学到了下面的内容,做个回顾吧。

JavaScript递归、预编译

2 学习内容

2.1 JavaScript是解释性语言,执行三部曲如下所示

首先,js对代码进行语法分析,查看有无低级语法错误
然后,进行预编译
最后,解释执行,即解释一行执行一行

2.2 通用规律

函数声明整体提升,变量声明提升

2.2.1 imply global暗示全局变量,即任何变量b,如果变量b未经声明就赋值,此变量就为全局对象所有,全局对象即为window.b可以在函数体外使用
例如:

1
2
3
4
5
6
7
function test() {
var a = b = 1;
console.log(a);
console.log(b);
}
test();
console.log(b);

2.2.2 一切在全局范围内声明的全局变量,全是window的属性
例如:

1
var a = 1;

就相当于

1
window.a = 1;

2.3 预编译

四部曲:

  1. 创建AO对象(即Activation Object,执行期上下文)
  2. 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
  3. 将实参值和形参统一
  4. 在函数体里面找函数声明,值赋予函数体

例子1:

1
2
3
4
5
6
7
8
9
10
11
function fn(a) {
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a);
var b = function () {}
console.log(b);
function d(){}
}
fn(1);

上面代码的预编译及执行过程如下

2.3.1.1 创建AO对象

    AO {

   }

2.3.1.2 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    AO {
            a : undefined;
            b : undefined;
   }

2.3.1.3 将实参值和形参统一

    AO {
            a : 1;
            b : undefined;
   }

2.3.1.4 在函数体里面找函数声明,值赋予函数体

    AO {
            a : f a() {};
            b : undefined;
            d : f () {};
   }

2.3.1.5 变量a已经提升声明,即在第2步已经优先声明,此处只需执行a = 123, b = f () {};

    AO {
            a : 123;
            b : f () {};
            d : f () {};
   }

例子2:

1
2
3
4
5
6
7
8
9
10
11
12
function test(a, b) {
console.log(a);
c = 0;
var c;
a = 3;
b = 2;
console.log(b);
function b() {}
function d() {}
console.log(b);
}
test(1);

上面代码的预编译及执行过程如下

2.3.2.1 创建AO对象

    AO {

   }

2.3.2.2 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    AO {
            a : undefined;
            b : undefined;
            c : undefined;
   }

2.3.2.3 将实参值和形参统一

    AO {
            a : 1;
            b : undefined;
            c : undefined;
   }

2.3.2.4 在函数体里面找函数声明,值赋予函数体

    AO {
            a : 1;
            b : f b() {};
            c : undefined;
            d : f d() {};
   }

2.3.2.5 变量a已经提升声明,即在第2步已经优先声明,此处只需执行c = 0; a = 3; b = 2;

    AO {
            a : 3;
            b : 2;
            d : f () {};
   }

例子3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function test(a, b) {
console.log(a);
console.log(b);
var b = 234;
console.log(b);
a = 123;
console.log(a);
function a() {}
var a;
b = 234;
var b = function () {}
console.log(a);
console.log(b);
}
test(1);

上面代码的预编译及执行过程如下

2.3.3.1 创建AO对象

    AO {

   }

2.3.3.2 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    AO {
            a : undefined;
            b : undefined;
   }

2.3.3.3 将实参值和形参统一

    AO {
            a : 1;
            b : undefined;
   }

2.3.3.4 在函数体里面找函数声明,值赋予函数体

    AO {
            a : f a() {};
            b : undefined;
   }

2.3.3.5 变量a已经提升声明,即在第2步已经优先声明,此处只需执行b = 234; a = 123; b = 234; b = f() {};

    AO {
            a : 123;
            b : f() {};
   }

注意:

上述在函数体中,生成AO对象,而在全局状态下生成GO对象
window === GO,但能使用window.a,不能使用GO.a

例子4:

1
2
3
4
5
6
7
8
console.log(test);
function test(test) {
console.log(test);
var test = 123;
console.log(test);
function test() {}
}
test(1);

上面代码的预编译及执行过程如下

2.3.4.1 创建GO对象

    GO {

   }

2.3.4.2 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    GO {
            test : undefined;
   }

2.3.4.3 将实参值和形参统一

    GO {
            test : undefined;
   }

2.3.4.4 在函数体里面找函数声明,值赋予函数体

    AO {
            test : ƒ test(test) {
                         console.log(test);
                        var test = 123;
                        console.log(test);
                        function test() {}
                };
   }

2.3.4.5 创建AO对象

    AO {

   }

2.3.4.6 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    AO {
            test : undefined;
   }

2.3.4.7 将实参值和形参统一

    AO {
            test : 1;
   }

2.3.4.8 在函数体里面找函数声明,值赋予函数体

    AO {
            test : ƒ test() {};
   }

2.3.4.9 变量test已经提升声明,即在第2步已经优先声明,此处只需执行test = 123;

    AO {
            test : 123;
   }

例子5:

1
2
3
4
5
6
7
8
9
   global = 100;
function test() {
console.log(global);
global = 200;
console.log(global);
var global = 300;
}
test();
var global;

上面代码的预编译及执行过程如下

2.3.5.1 创建GO对象

    GO {

   }

2.3.5.2 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    GO {
            global: undefined;
   }

2.3.5.3 将实参值和形参统一

    GO {
            global: undefined;
   }

2.3.5.4 在函数体里面找函数声明,值赋予函数体

    GO {
            global: undefined;
            fn : f () {
                  console.log(global);
                global = 200;
                console.log(global);
                var global = 300;
             };
   }

2.3.5.5 创建AO对象

    AO {
        
   }

2.3.5.6 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    AO {
            global : undefined;
   }

2.3.5.7 将实参值和形参统一

    AO {
            global : undefined;
   }

2.3.5.8 在函数体里面找函数声明,值赋予函数体

    AO {
            global : undefined;
   }

2.3.5.9 变量global已经提升声明,即在第2步已经优先声明,此处只需执行global= 200; global = 300;

    AO {
            global : 300;
   }

2.4 百度13年面试题

2.4.1 题目一

2.4.1.1 代码

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

上面代码的预编译及执行过程如下

2.4.1.2 创建GO对象

    GO {

   }

2.4.1.3 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    GO {
            
   }

2.4.1.4 将实参值和形参统一

    GO {
            
   }

2.4.1.5 在函数体里面找函数声明,值赋予函数体

    GO {
            bar : f () {
                    return foo;
                    foo = 10;
                    function foo () {}
                    var foo = 11;
                  };
   }

2.4.1.6 创建AO对象

    AO {
        
   }

2.4.1.7 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    AO {
            foo : undefined;
   }

2.4.1.8 将实参值和形参统一

    AO {
            foo : undefined;
   }

2.4.1.9 在函数体里面找函数声明,值赋予函数体

    AO {
            foo : f () {};
   }

2.4.1.10 变量foo已经提升声明,即在第6步已经优先声明,此处只需执行return foo;

    AO {
            foo : f () {};
   }

2.4.2 题目二

2.4.2.1 代码

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

上面代码的预编译及执行过程如下

2.4.2.2 创建GO对象

    GO {

   }

2.4.2.3 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    GO {
            
   }

2.4.2.4 将实参值和形参统一

    GO {
            
   }

2.4.2.5 在函数体里面找函数声明,值赋予函数体

    GO {
            bar : f () {
                    foo = 10;
                     function foo () {}
                     var foo = 11;
                     return foo;
        };
   }

2.4.2.6 创建AO对象

    AO {
        
   }

2.4.2.7 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    AO {
            foo : undefined;
   }

2.4.2.8 将实参值和形参统一

    AO {
            foo : undefined;
   }

2.4.2.9 在函数体里面找函数声明,值赋予函数体

    AO {
            foo : f () {};
   }

2.4.2.10 变量foo已经提升声明,即在第6步已经优先声明,此处只需执行foo = 10; foo = 11; return foo;

    AO {
            foo : f () {};
   }


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 xingshuaikun@163.com。

×

喜欢就点赞,疼爱就打赏