几乎全部的编程语言都有做用域的概念,并且理解该门语言做用域是掌握这门语言的必经之路。若是你要访问某个变量或函数,做用域则决定了你可否访问到,换句话说做用域控制着变量与函数的可见性和生命周期。javascript
记得刚刚学js的时候(其实当时压根没怎么学js,按照对Java的理解就直接开始用了),对于js的做用域这块彻底是按照Java的做用域来理解的,结果就这样写点简单的js倒也没有太大的问题,可是后来业务愈来愈复杂,须要写的js也愈来愈复杂,就发现js的做用域和Java的不同呢!(对于Java和JavaScript之间的关系还有疑问的同窗,只须要记住这两种语言的共同点就是名字都含有Java就是了。)那么js的做用域是怎么的样呢?下面咱们就说道说道。html
在js里面,以函数来分隔做用域,又称函数做用域: 做用域在函数内修改。 如:java
function scopeFunc(){ for(var i=0;i<5;i++){ //console.log(i); } console.log(i); } scopeFunc();//5 //若是js有块级做用域,那么在for循环外应该是取不到i的值的,应该报错,可是咱们照样取到了i的值;这里的i是局部变量 function scopeFunc2(){ for(let i=0;i<5;i++){ //console.log(i); } console.log(i); } scopeFunc2();//i is not defined //在ES6(ES2015)以前,咱们看到js是没有块级做用域的,可是ES6新有的定义变量的let关键字,能够定义块级做用域 function Student(name){ console.log(name);//ly var score; console.log(score);//undefined console.log(age);//ReferenceError: age is not defined } Student('ly'); console.log(name);//undefined;函数参数只在函数内起做用,是局部变量。 //咱们看到在函数内使用一个定义了可是未赋值的变量的时候,提示undefined,使用一个未定义的变量时提示出错了。 //scopeFunc是函数的句柄,在js中,对象和函数一样也是变量,此处,scopeFunc是全局函数,也是全局变量了 setTimeout(scopeFunc,500); //setTimeout这里用的是函数的句柄,若是写成setTimeout(scopeFunc(),500);会形成内存泄露 /* 最外层函数和在最外层函数外面定义的变量拥有全局做用域,因此声明全局变量比较简单,不过有种特殊的状况,在函数内, 若是不使用var声明,直接给变量赋值,这个变量直接就拥有全局做用域 */ function wholeScopeFn(){ testw='imwhole';//若是不使用var声明变量,此处就至关因而window.testw='imwhole'; var testpart='impart'; console.log(testpart); } console.log(testw);//ReferenceError: testw is not defined wholeScopeFn();//impart console.log(testw);//imwhole /* 全局变量咱们均可以经过window.变量名 的方式来获取,可是当使用var声明一个全局变量时, 建立的这个属性是不可配置的,也就是说没法经过delete运算符删除,不使用var声明的全局变量,能够经过delete删除 */ //函数运行在它们被定义的做用域里,而不是它们被执行的做用域里 function Student(name){ console.log(name);//ly var score; console.log(score);//undefined console.log(age);//ReferenceError: age is not defined } function myCare(){ var age=10; Student('ly'); } myCare(); //咱们看到,myCare函数内已经声明并初始化了一个变量age,而在Student函数内,在执行到打印age变量的时候任然提示为定义
总结一下就是变量在函数外定义,就是全局变量。 变量在函数内声明,就是局部变量, 只能在函数内部访问。编程
说了变量的做用范围,还得说说变量的生命周期。生命周期意味着你用了当前变量以后下次用的时候他得是个什么。简单的说,变量在他还能被用到的时候就不会被销毁,不能再被用到的时候就该销毁了,生命也就走到尽头了。如:编程语言
function scopeLife(){ var sl=0; console.log(++sl); } var wsl=0; scopeLife();//1 scopeLife();//1 scopeLife();//1 ;局部变量在函数执行完毕后销毁。 console.log(++wsl);//1 console.log(++wsl);//2 console.log(++wsl);//3 ;全局变量在页面关闭后销毁。
好的,咱们再来看看和做用域有关的一个有趣的地方,变量声明提高。函数
var name='ly'; function Student(){ console.log(name);//undefined var name='liuyong'; console.log(name);//liuyong } //上面的代码能够写成以下 var name='ly'; function Student(){ var name; console.log(name);//undefined name='liuyong'; console.log(name);//liuyong } //这样是否是好理解得多了,当执行函数的时候,会先函数内的变量的声明。 //若是函数内不写var直接定义全局变量,这样的变量是不会被提高的 function Student(){ console.log(name); name='liuyong'; console.log(name);//liuyong } Student();
说到js做用域,若是不说做用域链,会不会显得过低端了呢?哈哈,能够看下这两篇文章(JavaScript做用域链详细介绍,JavaScript 开发进阶:理解 JavaScript 做用域和做用域链),我的以为做用域链这块,这两篇文章讲得挺不错的。有什么问题也欢迎交流。spa