1.变量声明提升与函数声明提升
- 变量声明提升
- 通过var定义(声明)的变量, 在定义语句之前就可以访问到
- 值: undefined
- 函数声明提升
- 通过function声明的函数, 在之前就可以直接调用
- 值: 函数定义(对象)
- 问题: 变量提升和函数提升是如何产生的?
面试题: 输出什么?
*/
var a = 4
function fn () {
console.log(a)
var a = 5
}
fn() //undefined
/*变量提升*/
console.log(a1) //可以访问, 但值是undefined
/*函数提升*/
a2() // 可以直接调用
var a1 = 3
function a2() {
console.log('a2()')
}
2.执行上下文
- 代码分类(位置)
- 全局代码
- 函数代码
- 全局执行上下文
- 在执行全局代码前将window确定为全局执行上下文
- 对全局数据进行预处理
- var定义的全局变量==>undefined, 添加为window的属性
- function声明的全局函数==>赋值(fun), 添加为window的方法
- this==>赋值(window)
- 开始执行全局代码
- 函数执行上下文
- 在调用函数, 准备执行函数体之前, 创建对应的函数执行上下文对象
- 对局部数据进行预处理
- 形参变量==>赋值(实参)==>添加为执行上下文的属性
- arguments==>赋值(实参列表), 添加为执行上下文的属性
- var定义的局部变量==>undefined, 添加为执行上下文的属性
- function声明的函数 ==>赋值(fun), 添加为执行上下文的方法
- this==>赋值(调用函数的对象)
- 开始执行函数体代码
console.log(a1) //undefined
console.log(a2) //undefined
console.log(a3) //function a3() {console.log('a3()')}
console.log(a4) //报错
console.log(this) //window
var a1 = 3
var a2 = function () {
console.log('a2()')
}
function a3() {
console.log('a3()')
}
a4 = 4
function fn(x, y) {
console.log(x, y)
console.log(b1)
console.log(b2)
console.log(arguments)
console.log(this)
// console.log(b3)
var b1 = 5
function b2 () {
}
b3 = 6
}
fn()
重点案例
-
整个过程中产生了几个执行上下文?
n+1 n为调用函数的次数,1为全局的window
1.png
console.log('global begin: '+ i)
var i = 1
foo(1);
function foo(i) {
if (i == 4) {
return;
}
console.log('foo() begin:' + i);
foo(i + 1);
console.log('foo() end:' + i);
}
console.log('global end: ' + i)
- 先预处理变量, 后预处理函数
function a() {}
var a;
console.log(typeof a) //function
- 变量预处理, in操作符
if (!(b in window)) {
var b = 1;
}
console.log(b) //undefined
- 预处理, 顺序执行(易错指数)
var c = 1
function c(c) {
console.log(c)
var c = 3
}
c(2) //报错 c is not function
