作用域
| 1 | <script> | 
- 在JS中,函数嵌套是非常普遍的,在函数嵌套中,对变量进行如下的寻找方式:首先在函数内寻找,寻找不到,则往函数外层寻找,……,直到全局(window)区域
声明变量var
- var是在函数运行的上下文中,声明一个变量,如果不加var,则是一个赋值操作,但不要狭隘的理解为–>声明了一个全局变量【见下例】
| 1 | <script> | 
- 以window.xxx引用全局变量,寻找不到,作为某个属性不存在,返回undefined 【window.a】 
- 直接以xxx引用某个变量,寻找不到,则是报xxx is not defined错误的 【a】 
| 1 | <script> <script> | 
- JS代码自上而下执行,但是,JS代码在整体运行时分为【词法分析期】和【运行期】两部分 
- 自上而下执行之前,先有一个【词法分析】过程,以上面的结果为例: 
| 1 | 第一步:分析t1() | 
词法分析
语法分析,分析3样东西:
- 第一步:先分析参数 
- 第二步:在分析变量声明 
- 第三步:分析函数声明 
一个函数能使用的局部变量,就从上面的3步分析而来
具体步骤:
- 第一步:函数运行前的一瞬间,生成Active Object(活动对象),下称AO 
- 第二步:把函数声明的参数,形成AO的属性,值全是undefined,如果有实参,则接收,并形成AO相应的属性的值 
- 第三步:分析变量声明!如var age,如果AO上还没有age属性,则添加AO属性,值是undefined;如果AO上已经有age属性,则不做任何影响 
- 第四步:分析函数声明,如 function foo(){ },则把函数赋给AO.foo属性,如果此前foo属性已经存在,则被无情的覆盖 
| 1 | <script> | 
函数声明与函数表达式
- 函数可以赋值给变量,也可以作为参数来传递 
- JS被称为披着C外衣的lisp语言,lisp是一种强大的函数式语言 
| 1 | function t1(){} | 
作用域链
argumengs详解
- 是一个长得很像数组的对象 
- 内容是函数运行时的实参列表 
| 1 | //arguments收集“所有”的实参,即使没有与之相对应的形参 | 
函数运行期内,有三个关键的对象:
- AO ——> 本函数AO上没有某属性,则继续去外层函数的AO上找,直到全局对象,叫做 作用域链 
- arguments ——> 每个函数都有自己的callee,但不会向外层函数接着找arguments的相关属性,即不形成链 
- this ——> 也不形成链 
this详解
- 在JS中函数有4种调用方式
| 1 | alert(window.x); //输出 undefined | 
闭包
- 在大部分语言中,t1被调用执行,则申请内存并把其局部变量push入栈。t1函数执行完毕,内部的局部变量,随着函数的退出而销毁,因此age = 20的局部变量已经消息。 
- 但是在JS中,age = 20这个变量,却被t2捕捉,即使t1执行完毕,通过t2,依然能访问该变量 
- 像这种情况:返回的函数,并非孤立的函数,甚至把其周围的变量环境,形成了一封闭的“环境包”,共同返回,所以叫闭包。 
- 一句话概括:函数的作用域取决于声明时,而不取决于调用时!