这是第七章函数表达式,这一章涉及函数预编译,闭包,作用域链内容。函数涉及内容繁多。
前情提要 02-1 | 读JavaScript 高程 | 解释,这章的重点其实在函数预编译时发生事情。
我们知道对象是属性和方法的合集。而我们的函数其实也是对象,所以对象上的一些东西,或者说原型链上的方法是可以使用的。
通过实验来了解一些这波知识。
那么问题来了,第一步如何逮到实验要用的小白鼠。
1.函数的创建方式有哪些?
实验小白鼠通过培养或者去逮一下,那么我们的实验用品函数如何培养出来?
目前来讲有以下几种方案:
- 函数声明
- 函数表达式
- 匿名函数
- 箭头函数
- 函数生成器
这里的点在于ES6中新增的箭头函数和ES7新增的函数生成器。
2.函数有什么方法?
函数是对象,它有 name 和 length 方法。
[(function a(){}).name, (function b(c, d){}).length]
// ["a", 2]
name 代表函数名,length 代表函数形参的数量。
3.函数运行
- 加()
- call apply
站在编写代码的角度,函数的使用分两步,定义和运行,下面站在浏览器或者说编译器的角度来看一看。
4.js运行三步曲
- 词法分析
- 预编译
- 解释执行
词法分析,通篇扫描,看看有没有语法错误。
进入紧张刺激的预编译环节。
sayHi()
function sayHi() {
console.log('hi')
}
sayHi()
甭管是在函数声明前调用还是在函数声明后调用,都能得到结果,这是为什么?
换一种函数定义方式,为什么会报错误?
a()
var a = function () {
console.log('hi')
}
a()
// a()
// ^
// TypeError: a is not a function
未定义前 a 是个什么玩意?
console.log(a)
var a = function () {
console.log('hi')
}
a()
// undefined
// hi
上面这些状况是在预编译时引发的,那么在预编译时,函数受到了怎样的待遇?这是怎样的一套规则?
5.预编译的过程(全文背诵)
预编译发生在函数执行的前一刻。
imply global:全局对象所有:全局变量,未经声明就赋值的变量。
来个例子:
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)
预编译的过程:
-
创建AO对象,Activation Object 执行期上下文。
-
找形参和变量声明,将变量和形参名作为AO属性名,值为undefined。
3.将实参和形参相统一。
4.在函数体里找函数声明,值赋予函数体。
// 按照上面步骤走两步
1.
AO {
}
2.
AO {
a:undefined,
b:undefined
}
3.
AO {
a:1,
b:undefined
}
4.
AO {
a:function a() {},
b:undefined,
d:function d() {}
}
解释执行时用到的AO:
AO {
a:function a() {},
b:undefined,
d:function d() {}
}
function fn(a) {
console.log(a) // function
var a = 123
console.log(a) // 123
function a () {}
console.log(a) // 123
var b = function () {}
console.log(b) // function
function d() {}
}
fn(1)
题目:
console.log(a)
var a = 123
// undefined
console.log(a)
function a(a) {
var a = 1997
var a = function () {}
a()
}
var a = 2020
网友评论