JS的运行
执行环境、上下文、闭包或块与块级作用域
-
语句执行的意义
- 语句是命令,语句执行都最终会以一个完成状态来返回。
- 完成状态有五种:normal、return、break 、continue、throw。
- 中断类型
- break; 中断当前语句,将执行逻辑交到下一语句。应用于循环/switch语句中
- break labelName; 中断“任意的标签化语句”,应用于块中
- break语句的返回值的两个特性:类型必然是“break”;返回值必然是“空(Empty);
- x break x;
- 中断类型
- JavaScript 是一门混合了函数式与命令式范型的语言,而这里对函数和语句的不同处理,正是两种语言范型根本上的不同抽象模型带来的差异
-
特殊的可执行结构-模板
-
可执行结构
模板;迭代器;赋值模板;指令
归类于名字和值的绑定 -
特殊的可执行的逻辑: 逐一匹配->把实参放在arguments列表中,然后让arguments中的值与参数表中的名字对应起来。
- 箭头函数没有参数表?也采用与上述处理逻辑,只是在最后没有向闭包绑定arguments这个名字而已。
- 所谓简单参数,就是可以在形参表中明确参数个数、没有扩展风格的参数表。
-
扩展风格的参数表
-
缺省参数,剩余参数,参数展开(依赖于迭代器)
-
模板字面量
${1}
是可执行结构的集大成者,
它存储的是“结果”与“结果的计算过程”之间的关系,但是关注的是值,
当它作为值来读取时,就会激活它的运算求值过程,并返回一个字符串值。 -
throw语句
- 值的覆盖与读取
有语句的执行结果值的可能范围:empty(if/while/try/for..语句不允许返回empty),或一个既有的执行结果值(包括undefined)
- 值的覆盖与读取
-
函数的执行过程
- 函数的一体两面
- 用静态的视角来看,函数也无非就是“用三个语义组件构成的实体”: 参数+执行体+结果。
函数既是可执行的逻辑,也同时是可被逻辑处理的数据。
函数作为数据时,是“原始的函数声明”的一个实例,实例必须包括三个语义组件中的参数与执行体,创建了一个闭包作为结果。闭包(一个执行环境)是函数在运行期的一个实例。
-
初始化参数(参数登记过程
- 简单参数x:“直接arguments绑定”. 只需要映射实参与参数对象(形参)两个数组的下标即可,
- “非简单参数”:“初始器赋值”. 通过名字来绑定索引值,因此一旦出现“重名参数”就无法处理了。
初始器赋值时,无初值绑定,不可访问(类似于let变量
-
传入参数
执行于函数之外,例如f(a=100)
函数参数与函数内变量同名,那么它们事实上将是同一个变量。
对于简单参数x来说,没有“求值过程x=100”发生于函数的调用界面上 -
绑定参数
绑定参数的过程执行于函数(的闭包)之内,例如function foo(x=100)
(x = x) => x
三个 x 都是指向相同的变量,
函数在尝试执行“初始器赋值”时会访问第2个x,由于x是未赋值的,如同 let 变量一样不可访问,从而触发异常。
x => x
是一个最小化的函数。包括了一个函数完整的三个语法组件:参数、执行体和结果。
=两端是一个值操作,反映了“函数”的本质-“数据的转换”==> 所有的函数与表达式求值的本质-将数据x映射成x' -
迭代与递归
-
递归:“函数调用自己”;迭代:“函数体”的重复执行
-
迭代过程展开:变成生成器函数与yield运算
- 生成器特点
所有其他上下文都在执行栈上,而生成器的上下文(多数时间是)在栈的外面。 - yield运算符
特点: 在挂起当前函数时,还将函数所在栈上的执行现场移出调用栈
作用: 产生一次函数的退出,传出指定的值,并接受下次tor.next()调用,传入所需数据
- 生成器特点
-
x=yield x
yield向函数外发送计算表达式x的值;yield接受外部传入的参数并作为结果值赋给 x。 -
展开语法“…x”
- 本质上是将x视为一个可迭代对象,通过一个迭代变量来管理它的迭代过程。
- 是没有向内通知的能力的(如通知return/throw事件);
而“for … of”可以隐式地向内通知。 - (...x) 不是表达式、语句、函数,不能被执行
-
没有名字的函数在语言中的意义
它既是逻辑,也是数据- 箭头函数并不绑定“this”和“arguments”
- 匿名函数或简头函数赋给一个变量作为函数名时,该函数名不会绑定给环境,只出现在它的属性中f.name。