JS读书笔记(四)变量作用域

未定义的变量

未声明的变量

未赋值的变量

 

未定义的变量 = 未声明的变量

 

  • 尝试读取未声明的变量会引起运行时错误。
  • 尝试给未声明的变量赋值不会引起错误,相反,程序会在全局作用域中隐式地声明它。
  • 尝试读取未赋值的变量,将会得到一个默认值,即undefined。

变量作用域的基本规:

  • 在域中以var声明的变量只在当前域或者当前域的子域起作用。
  • 对变量的查找总是从当前域开始,递归向上查找各级嵌套父域,最后到达全局。因此如果给一个当前域的局部变量与父域中的局部变量或者全局变量起相同的的名字,就能有效地隐藏上级变量或全局变量。
  • javascript除函数外的任何程序段落都不是独立的域。换句话说javascript没有块级作用域
    for(var i = 10;i < 10;i++)
      {
         do something
      }
    
    alert(i);// i = 9
     

javascript变量作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,编译器通过静态分析就能确定,因此词法作用域也叫静态作用域。

 

javascript在执行每个函数实例时,都会创建一个执行环境,执行环境里包括一个调用对象,调用对象是一个scriptObject,用于保存内部变量表,内嵌函数表,父级引用表等语法分析结构 (注意内部变量表和内嵌函数表等信息是在语法分析阶段就已经得到,并保存在语法树中。函数实例执行时,会将这些信息从语法树复制到scriptObject上)。

 

var arg = 1;
function funcTest() {
    alert(arg);
    var arg = 2;
}
arg = 10;
funcTest();

 

 该函数的输出是undefined而不是10,因为在funcTest函数执行时,进入funcTest对应的作用域,在执行到alert时遇到了变量名arg,则会在当前作用域中查找,由于arg = 2被定义在alert方法,所以在开始编译的时候,(词法分析已经获得定义的变量和方法,这也正说明了:变量作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,编译器通过静态分析就能确定 )这当前作用域中存在变量arg,但并没有赋值,故arg的值为undefined。

 

说的很好的一篇关于作用域的文章

 

另一篇文章里对作用域的说明:

 

JavaScript中的函数是基于静态作用域(也叫词法lexical作用域),而不是动态作用域。这句话的意思是JavaScript中的函数运行在它们被定义的作用域里 ,而不是它们被执行的作用域里 。在一个静态作用域里,变量永远指向它的最顶层作用域 。这是程序文本(program text)的一个属性并且与运行时调用的堆栈无关。因为匹配变量的作用域仅仅只需要分析程序文本即可,这样的作用域我们叫作静态作用域(lexical scoping)

function f1() {
   var a = 20;
   return function () { alert(a); }
}

var b = f1();
b();

结果:20

 

function f1() {
    var a = 20;
    return f2
}

function f2() {
   alert(a);
}

var b = f1();
b();

 结果:undefined ( 其实是报错的,因为引用了未定义的变量)

 

在程序1里一个匿名函数b() 被声明时,变量a 已经被保存在作用域里。所以得到20.但是在程序2里在函数f2() 里,没有声明变量a 所以没有任何值。

一但函数被定义,它会“记住”它的作用域与作用域链。这也并不是意味着函数里的所有变量都是这样。正好相反,你可以任意的添加、修改和删除。函数里都会保存最新的变量。但是必须知道变量是什么时候被定义而并不是这个作用域里它什么时候包含的。

 

静态作用域的几个特点

  • 在程序里特殊地方定义的变量永远指向具有相同定义的变量,即程序每次执行时被执行函数所在的作用域里相同定义的变量 (这句话没咋明白)
  • 变量是可以通过静态检查(static examination)源码中的作用域里出现的标识符(var)来将其值(value)改变的,而不是把整个函数做为一个整体来执行。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值