作用域、执行环境、闭包

今天开始一个小系列,我们从作用域开始,分别讲述作用域、作用域链、执行环境,最终为了学习理解JavaScript中一个很经典的概念:闭包

闭包是JavaScript中比较高级的概念和技巧,也是难理解的部分,必须熟练掌握函数表达式、作用域、变量的生存周期等概念后,才能掌握闭包的技巧。

作用域

我们已经知道了变量的概念,不管变量是基本数据类型还是引用类型,其都有一个作用范围,称之为作用域,超出该变量的作用域,则不能被访问,否则将会异常。如果该变量能被所有代码访问,称之为全局变量,其作用域为整个代码环境,反之为局部变量,其作用域为局部。可以将作用域的机制想象为行政管辖范围:县长只能管辖整个县、而市长可以管辖整个市、省长可以管辖整个省。

我们先来看以下代码:

var name=""张三";

function setname(){

name="李四";

}

function showname(){

alert(name);

}

showname();      //显示“张三”

setname();

showname();      //显示“李四”

分析以上代码,我们首先声明了一个变量name并给其赋值为“张三”,由于该变量的声明不在任何函数内,因此其为全局变量,作用域为全局环境,可在整个代码中对其访问,所以可以在函数setname()对其改写,并在函数showname()中对其访问。

接下来对代码做如下修改:

function setname(){

var name="李四";

alert(name);

}

function showname(){

alert(name);

}

showname();      //显示空

setname();       //显示“李四”

showname();      //显示空

我们把变量name的声明移至函数setname()内部,因此name的作用域范围只是函数setname()内部,而在函数showname()中访问不到变量name,因此显示为空。

继续看以下的代码:

function setname(){

var name="李四";

alert(name);

}

function setothername(){

var name="张三";

alert(name);

}

setname();             //显示“李四”

setothername();       //显示“张三”

虽然在函数setname()和setothername()都声明了name变量,但由于两个变量name的作用域均为函数内部,因此这两个变量name仅仅是名称相同而已,实际上是完全不同的两个变量,具有了不同的值。

接下来我们看一个较复杂的例子,函数内嵌套函数,可以更好的诠释变量声明的位置如何决定其所拥有的作用域:

var name="张三";

function changename(othername){

function swapname(){

var tempname=othername;

othername=name;

name=tempname;

//此处可以访问name、tempname、othername

}

swapname();

//此处可以访问name、othername,但不能访问tnepname

}

changename("李四");

alert(name);      //显示“李四”

//此处仅可访问name

分析以上代码,这是个改变姓名的函数,首先我们声明了全局变量name,其能被所有代码访问,接下来声明函数changename(),其传入参数为othername,因此函数changename()可以访问name、othername两个变量,在函数changename()中又声明了函数swapname(),在其内部又声明了局部变量tempname,所以函数swapname()可以访问name、othername、tempname三个变量。但变量tempname不能被函数swapname()以外的代码访问,同样传入参数othername也不能被函数changename()以外的代码访问。

下一讲我们将学习执行环境、作用域链。

欢迎加入技术QQ交流群:364595326

你可能感兴趣的:(javascript,函数,闭包,全局变量,数据)