这一周准备的有点晚,但“药”不能听,乱弹也不能听,这次我们就再说个基础的概念吧
作用域。
好,先本着专业精神来看,我们先看下维基百科的定义:
在电脑程序设计中,作用域(scope,或译作有效范围)是名字(name)与实体(entity)的绑定(binding)保持有效的那部分计算机程序。不同的编程语言可能有不同的作用域和名字解析。而同一语言内也可能存在多种作用域,随实体的类型变化而不同。作用域类别影响变量的绑定方式,根据语言使用静态作用域还是动态作用域变量的取值可能会有不同的结果。
- 包含标识符的宣告或定义;
- 包含语句和/或表达式,定义或部分关于可执行的算法;
- 嵌套嵌套或被嵌套嵌套。
名字空间是一种作用域,使用作用域的封装性质去逻辑上组群起关相的众识别子于单一识别子之下。因此,作用域可以影响这些内容的名字解析。
程序员常会缩进他们的源代码中的作用域,改善可读性。
嗯,好吧,这个定义好像看起来真的有点难懂,相对来说,百度百科给的定义稍微好懂一些:
作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突。
对于对象而言(其他也是一样的),在main函数中,对象的作用域为他所在的最近的一对花括号内。在后花括号处析构函数被调用;全局的对象的作用域为声明之后的整个文件,析构函数在最后被调用。另外,临时产生的对象在使用完后立即会被析构。
百度给的定义里面第三段是与语言有关的,可以忽略,那么我们更简单点理解就是一个变量的可用性范围的判断,而这个问题在JavaScript这门有点“奇怪”的语言上来说,还更灵活一些,不是那么好掌握。
好了,前面“啰嗦”了不少定义,接着就先从一个实例上分析下吧:
前端乱弹99日之作用域
给你1分钟时间,想一下会输出什么?
嗯,对的,没错,输出的结果如下:
sum:0
inside function a,sum=1
inside function b,sum=0
那么我们分析一下:
sum这个变量作为全局变量,输出 sum:0
这一行,应该是没有什么疑问的
接着调用a这个函数,进入之后,在函数内部又定义了一个sum变量,这时要注意的是,这个sum的可用性是只在a这个函数范围之内的。那么这个时候接着输出inside function a,sum=1
也是可以正常理解的。
接着在a函数内,再次调用b函数,而在b函数里是需要直接输出sum这个变量,而在b函数内是没有sum这个变量的定义的,那么这时就会往b函数的上一级去找有没有sum这个变量的定义,一看,嘿,还真有,就是咱们定义的全局变量sum = 0
嘛,这时,输出 inside function b,sum=0
当然是没有问题的嘛
好,上面的分析中,其实有一个同级和上级的概念蛮重要的,为了说明这个问题,我们再把上面的这个代码改一改看看:
前端乱弹99日之作用域
嗯,再给你一分钟,想想看,这个时候会输出什么?
对,答案如下:
sum:0
inside function a,sum=1
inside function b,sum=1
嗯,你想对了吗?从程序上,我们将b这个函数放在了a这个函数内部,那么当b函数内找不到sum这个变量的时候,他的上一级就是a这个函数里,一看,嘿,又sum,那么我就用咯。
嗯,其实今天说的这个不仅仅是作用域了,可以有一个更“高大上”的名称“作用域链”。
对于上面的程序中,还有一个“潜在”的问题,建议你试试看,就是把a方法里的var sum = 1
这个定义里的var去掉,看下结果,然后再想想看?可以从全局变量、局部变量的角度思考思考看?
最后,在当前ES6大行其道的时候,let这个关键字对于作用域的“重新定义”,也需要好好了解,和运用。【好吧,我承认我有点偷懒,这部分五一放假期间一定会补上】
最后扯两句别的,作为一个“后端狗”,学习前端的时候,并没有那么急切的想迅速做个项目出来,更优先去“夯实”自己的基础,也对比后端的语言,完善自己的知识结构。不做一个“面向搜索引擎编程”的程序员,从我做起!