第六讲 《javascript 递归 预编译 上》
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了第六讲 《javascript 递归 预编译 上》,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7261字,纯文字阅读大概需要11分钟。
内容图文
![第六讲 《javascript 递归 预编译 上》](/upload/InfoBanner/zyjiaocheng/718/fd311d4b81df49c99ff2614ba4dd0180.jpg)
javascript 递归 预编译 上
js运行顺序 (js 单线程 解释性语言)
- 语法分析 语义分析 (通篇扫描一遍 检查低级语法错误)
- 预编译
- 解释执行 (解释一行 执行一行)
讲解预编译之前 看一个现象:
1>
function tets() {
console.log("this is test Fun")
}
tets() // ==> "this is test Fun"
2> //有预编译参与
tets() // ==> "this is test Fun"
function tets() {
console.log("this is test Fun")
}
3>
let a = "this is var";
console.log(a) // ==> "this is var"
4>
console.log(a) //报错 若使用 var 定义变量 则会输出 undefined
let a = "this is var";
5>
console.log(a) //报错
- 函数声明账号整体提升
函数不管定义在哪里,系统都会提到逻辑之前
- 变量 声明 提升
变量不管声明在哪里, 系统都会把 变量的声明部分(不包含赋值 只有声明)放到程序的最前面
//例如变量的声明
let c = 666
预编译的时候: 会拆成两部分
let c;
c = 666
-
imply global 暗示全局变量: 即 任何变量 如果变量未经过声明就赋值, 此变量就为 全局对象(window) 所有
a = 132 等价于 window.a = 132 function test() {// a 是经过声明的, b 没有经过声明,所有 b 是全局变量, a 是局部变量 var a = b = 111 } test() console.log("b:",b)// 111 console.log("a:",a)// undefined
-
一切声明的全局变量, 全是 window(window 在 JS 中是一个 全局的域) 的属性
var a = 123 等价于 window.a = 123 function test() { var b = 111 //局部声明的变量 } test() console.log(b) // undefined
下面这段代码 预编译处理:
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)
预编译 (函数的预编译)的执行顺序 (4步) 预编译 发生在 函数被执行的前一刻
- 创建 AO 对象 (Activation Object 活跃对象 执行期 上下文 作用域)
AO{ }
- 找 形参名称 和变量声明名称,将变量和形参名作为 AO 属性名, 值为 undefined
//找函数中 的 形参 和变量名称 值为 undefined AO{ a: undefined, b: undefined }
- 将实参值 和形参值 统一 (仅仅实参 对应的 形参)
//将 实参的值 替换 undefined AOP{ a: 1, b: undefined }
- 在函数体里面 找函数声明 function name(){}(非函数的表达式声明 var name function (){}),并 赋值函数体
//将 函数声明体 替换 undefined AOP{ a: function a() {}, b: undefined, d: function d() {} }
》》》》开始执行函数!
预编译 处理过的 语句(优先执行), 解释执行环节会自动跳过,反之 没有经过预编译处理的函数,在解释执行的时候 会被执行
//预编译 执行过的 语句, 解释执行环节会自动跳过,反之 没有经过预编译处理的函数,在解释执行的时候 会被执行
function fn(a) {
console.log(a); //在完成预编译 AO对象中 a: function a() {}; 输出:? a() {}
var a = 123; //预编译环节没有对 赋值进行干预;所以 a = 132 可以正确执行;
console.log(a) //输出:123
function a() {}//(函数声明) //预编译环节中对 函数声明有做干预;所以值得函数执行过程中 跳过
console.log(a) //输出:123
var b = function () {}//(函数表达式) //预编译环节中对 对函数进行拆分 这里同等与 b = function () {};函数执行的时候还 类似 赋值 处理
console.log(b) //输出:123
function d() {}
}
//变量提前 函数提前
fn(1)
例子A:
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)
预编译阶段
- 生成 AO 对象
AO{ }
- 找 形参声明 和 变量声明, 把 形参对象名称 和 变量声明的名称 作为 AO 对象的属性名称,值为 underfined
AO{ a:undefined, b:undefined, c:undefined }
- 形参 实参,形参相统一,形参替换为实参 (仅仅实参 对应的 形参)
AO{ a:1, b:undefined, c:undefined }
- 找函数声明,把函数声明的名称 作为 AO属性的名称(可能会替换之前的形参名),把值作为 属性名称对应的 函数体
AO{ a:1, b:function () {}, c:undefined, d:function () {} }
>>>>解释执行阶段
function test(a, b) {
console.log(a); //输出 1
c = 0; //c 赋值 0 AO{} 中的 C 也被赋值为 0
var c; //预编译阶段预先执行,解释执行阶段 跳过
a = 3; //a 赋值 3 AO{} 中的 a 也被赋值为 3
b = 2; //b 赋值 2 AO{} 中的 b 也被赋值为 2
console.log(b); //输出 2
function b() {}
function d() {}
console.log(b) //输出 2
}
执行完毕后 AO 变成这样:
AO{
a:1, ===> 3
b:function () {}, ===> 2
c:undefined, ===> 0
d:function () {}
}
例子B:
function test(a, b) {
console.log(a)
console.log(b)
var b = 234;
a = 123;
console.log(b)
function a() {}
var a;
b = 234;
var b = function () {}
console.log(a)
console.log(b)
}
test(1)
>>>>>>预编译阶段:
- 生成 AO对象
AO{ }
- 将 形参 以及变量 名称, 作为 AO对象的 属性名,值为 undefined
AO{ a:undefined, b:undefined, }
- 将 实参 的值 替换为形参的 值(undefined) 不包含变量的 赋值替换
AO{ a:1, b:undefined, }
- 找 函数的声明, 将函数声明 的名称。作为 AO对象 的 属性名,(会对第二阶段 生成的 AO对象属性 进行同名覆盖 ) 并将函数体 赋值给对应的属性名
AO{ a:function(){}, b:undefined, }
>>>>>>解释执行:
function test(a, b) {
// AO 对象 预编译 第四阶段的初始值
// AO{
// a:function(){},
// b:undefined,
// }
console.log(a) //输出 fun ===> AO对象的 a
console.log(b) //输出 undefined ===> AO对象的 b
var b = 234; //等同 b = 234;
// AO 对象 修改
// AO{
// a:function(){},
// b:234,
// }
a = 123; //赋值操作
// AO 对象 修改
// AO{
// a:123,
// b:234,
// }
console.log(b) //输出 234
function a() {} //预编译 第四 阶段 处理过; 解释执行阶段 跳过
var a; //预编译 第四 阶段 处理过; 解释执行阶段 跳过
b = 234; //赋值操作
// AO 对象 修改
// AO{
// a:123,
// b:234,
// }
var b = function () {}//等同 b = function(){} 赋值操作
// AO 对象 修改
// AO{
// a:123,
// b: function(){},
// }
console.log(a) //输出 132
console.log(b) //输出 ? () {}
}
test(1)
>>>全局预编译顺序: 和上面的预编译类似 只是这里 生成了 GO 对象
GO === window
function test(){
var a =ab = 123;
console.log(ab) //输出:132
console.log(window.ab) //输出:132 ab 为全局变量
}
test()
未声明的变量 直接赋值 为全局变量
AO{
a = 123
}
GO{
ab = 123
}
先 GO ===> AO
例子C
console.log(test);
function test() {
console.log(test)
var test = 234;
console.log(test)
function test() {}
}
test(1)
var test = 123
四个阶段 预编译:
- GO
GO{ test:function test() { console.log(test) var test = 234; console.log(test) function test() {} }, }
- AO
AO{ test: function test() {} }
>>>>解释执行阶段
// GO 预编译结束后的 的 初始值
//
// GO{
// test:function test() {
// console.log(test)
//
// var test = 234;
//
// console.log(test)
//
// function test() {}
//
// }
// }
// AO 预编译结束后的 的 初始值
//
// AO{
// test: function test() {}
// }
console.log(test); //输出: GO 的 test
function test() { //预编译处理过了, 解释执行 跳过
console.log(test) //输出 AO.test
var test = 234; //等价于 AO.test = 234
// AO{
// test: 234
// }
console.log(test) //输入 234 AO.test
function test() {} //预编译处理过, 解释执行跳过
}
test(1) //跳过
var test = 123 //等同 test = 123
// GO{
// test: 132
// }
例子D:
global = 100;
function fn() {
console.log(global)
global = 200
console.log(global)
var global = 300
}
fn()
var global
- GO
GO{ global:100 fn:function f() { //... } }
- AO
AO{ global:undefined }
// GO{
// global:100
// fn:function f() {
// //...
// }
// }
global = 100;
function fn() {
// AO{
// global:undefined
// }
console.log(global) //输出 undefined
global = 200 //赋值 AO.global = 200
// AO{
// global:200
// }
console.log(global) //输出 200
var global = 300
}
fn()
内容总结
以上是互联网集市为您收集整理的第六讲 《javascript 递归 预编译 上》全部内容,希望文章能够帮你解决第六讲 《javascript 递归 预编译 上》所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。