概念
作用域(scope)是结构化编程语言中的重要概念,它决定了变量的可见范围和生命周
期,正确使用作用域可以使代码更清晰、易懂
作用域可以减少命名冲突,而且是垃圾回收的基本单元
结构化编程语言:就是适合进行结构化程序设计的语言,比如说面向过程的C语言;
简而言之就是运行原理能有效的模拟程序框图的语言,通常面向过程的编程语言都是结构化编程语言;
常见编程语言C、C++、Java 等,都以花括号作为块级作用域
而js并没有此限制,
js只以函数决定作用域,其他if等的花括号不作为独立作用域
if (true) {var some = \'hello\'}console.log(some)//hello
该例子在js没有问题,但是放在c中就会报错
但是js在es6中也解决了该问题,通过let,将花括号{}作为块级作用域
函数作用域/局部作用域
JavaScript 的作用域是通过函数来定义的,在一个函数中定义的变量只对这个函数内部可见,
我们称为函数作用域。在函数中引用一个变量时,JavaScript 会先搜索当前函数作用域,或者称为“局
部作用域”,如果没有找到则搜索其上层作用域,一直到全局作用域。
var version = \"version_1\";var f2 = function() {var version = \"version_2\";console.log(version);//version_2}f2();//js先搜索局部活动对象(变量)后搜索全局活动对象
var version = \"version_1\";var f1 = function() {console.log(version);//version_1}f1();
var socpe = \"scope_01\";var f3 = function() {console.log(scope);var scope = \"scope_02\";}f3();//js首先搜索局部,发现有此变量,但是变量在他之后 ,执行变量提升,var f3 = function() {var scopeconsole.log(scope); //undefinedscope = \"scope_02\";}//所以打印为undefined
var x_scope = \"leo\";var f5 = function() {console.log(x_scope); //leo}var f6 = function() {var x_scope = \"jut\";f5();}f6();//javascript函数嵌套时,作用域是由嵌套关系决定的,调用的顺序忽略不记//f5的作用域只有自己的局部和全局,并不包括f6
注意 函数内没有声明的变量(在任何地方隐式定义的变量(未声明直接赋值的变量)),自动声明为全局
模块儿化编程的一个重要原则就是避免使用全局变量,所以在任何地方都不应该隐式定义变量
var f3 = function() {scope = \"scope_02\";}f3();console.log(scope)//scope_02
全局作用域 Global Scope
在代码的任何地方都可以访问到的对象,比如window对象及window对象的属性,就拥有全局作用域。
1、在最外层定义的变量,默认都是window对象的属性;
2、未定义的变量默认都是全局的,默认也都是window对象的属性;
var firstName = \"leo\";function changeName() {var secondName = \"jut\";fullName = \"jutleo\";function getName() {console.log(secondName);}getName();}console.log(firstName);//leoconsole.log(fullName);//报错console.log(secondName);//报错changeName();//jutconsole.log(fullName);//jutleoconsole.log(secondName);//报错
作用域的注意点
javascript在查找变量时,顺序往上找的这个链条就作用域链。在实际应用中变量的位置越深,读写的速度就越慢,直到找到全局作用域中。
function setLabelBgColor(){document.getElementById(\"btn\").οnclick=function(){document.getElementById(\"label\").style.backgroundColor=\"red\";};}
根据作用域链的查找逻辑,查找document变量必须遍历整个作用域链,直到最后在全局对象中才能找到,这个函数引用了两次。优化如下:
function setLabelBgColor(){var doc = document;doc.getElementById(\"btn\").οnclick=function(){doc.getElementById(\"label\").style.backgroundColor=\"red\";};}
这么做并不会大幅提升性能哦!但是在实际使用中要避免全局变量被大量访问的情况