深入理解javascript之作用域
2015-06-23 19:22
483 查看
简单地说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在javascript中,变量的作用域分为全局和局部两种。
拥有全局作用域就是在代码任何地方都能够访问到,叫做全局变量,以下三种情况可以拥有
未定义直接赋值的变量:
所有window对象:
一般情况下,所有window对象的内置属性都拥有全局作用域,如window.location等。
如下代码:
举个例子说,
最后结果的lf而不是brizer。说明函数在定义时,它的作用域就已经决定了。
比如下面代码:
在函数创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量,如下图:
当函数被执行时,会创建一个活动对象,该对象包含了函数所有局部变量、命名参数以及this,然后该对象会被推入作用域链的前端,当函数执行完毕,该对象也随之销毁。如下图:
可以看到,全局变量会被活动对象推到作用域链的最后端,这也就是为什么全局变量访问速度慢的原因!
拥有全局作用域就是在代码任何地方都能够访问到,叫做全局变量,以下三种情况可以拥有
全局作用域
最外层函数和最外层函数外面定义的变量:var name="brizer"; function doSomething(){ var realname="lf"; function innerSay(){ alert(realname); } innerSay(); } document.write(name); //brizer document.write(realname); //脚本错误 doSomething(); //lf innerSay() //脚本错误
未定义直接赋值的变量:
/*全局作用域2:*/ function doSomething(){ var name="brizer"; realname="lf"; document.write(name); } doSomething(); //brizer document.write(realname); //lf
所有window对象:
一般情况下,所有window对象的内置属性都拥有全局作用域,如window.location等。
局部作用域
局部作用域只在固定的代码片段内可访问到。如下代码:
function doSomething(){ var name="lf"; function innerSay(){ alert(name); } innerSay(); } alert(name); //脚本错误 innerSay(); //脚本错误
函数作用域
这里把函数作用域单独提出来讲并不是因为它和局部还有全局是平级关系,而是由于其比较特殊。JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里。这是javascript权威指南中的一句话,相当经典。举个例子说,
//函数运行在它们被定义的作用域里,而不是它们被执行的作用域 var name = 'lf'; function echo() { document.write(name); } function env() { var name = 'brizer'; echo(); } env();
最后结果的lf而不是brizer。说明函数在定义时,它的作用域就已经决定了。
作用域链
下面我们说说作用域链,在javascript中,函数也是对象,实际上,javascript中的一切都是对象。函数内部有一个只给javascript引擎访问的内部属性是[[scope]],该属性包含了函数创建时的作用域中对象的集合,这个集合就叫做作用域链。比如下面代码:
function add(num1,num2) { var sum = num1 + num2; return sum; }
在函数创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量,如下图:
当函数被执行时,会创建一个活动对象,该对象包含了函数所有局部变量、命名参数以及this,然后该对象会被推入作用域链的前端,当函数执行完毕,该对象也随之销毁。如下图:
可以看到,全局变量会被活动对象推到作用域链的最后端,这也就是为什么全局变量访问速度慢的原因!
with
一般情况下,作用域链只会被with和catch语句影响。当使创建用with的时候,函数会创建一个新的活动对象,推到最前端,该对象就是with的对象。这就意味着所有的局部变量都处于第二个作用域链对象中去了,这也就是为什么要避免使用with的原因。function initUI(){ with(document){ var bd=body, links=getElementsByTagName("a"), i=0, len=links.length; while(i < len){ update(links[i++]); } getElementById("btnInit").onclick=function(){ doSomething(); }; } }
相关文章推荐
- javascript之面对对象设计
- js中typeof的用法汇总[转载]
- js遍历数组和遍历对象的区别
- javascript工具--控制台详解(转自 阮一峰博客)
- Javascript性能优化案例
- js中setTimeout与setInterval
- jni 移植 JNI环境变量char, jstring 的相互转化
- js 分享qq空间,新浪微博,qq
- 深入浅出jsonp
- JS中自执行的匿名函数
- JavaScript 的性能优化:加载和执行
- 深入浅出jsonp
- js定义对象的两种方法以及js用call来实现类的继承
- JS闭包
- ResponsiveSlides.js最轻量级的幻灯片插件
- js、jq怎么控制文本框只能输入数字
- $.getJson
- 1、使用javascript代码写出一个函数:实现传入两个整数后弹出较大的整数
- JS方法代理
- extjs传递参数