javascript作用域和闭包
来源:互联网 发布:知乎 wings颁奖 编辑:程序博客网 时间:2024/06/05 08:38
执行环境
在了解作用域前,先了解一下执行环境,也叫执行上下文。每个函数都有一个自己的执行环境,书中(javascript高级程序设计)说明
每个执行环境都有一个 与之关联的变量对象(variable object)。
我们不妨将这个执行环境看做这个对象,它里面包含了在函数中定义的变量、函数等。函数定义时,会生成该函数的执行环境。当函数被执行时,该执行环境(该对象)被推入环境栈中,执行完毕时,该对象会被弹出销毁。然后执行环境会改为当前栈顶的对象。
默认的环境变量是全局环境,与之关联的对象就是window。局部环境的关联对象开始只有一个变量-arguments
作用域和作用域链
作用域控制着变量与参数的可见性及生命周期。关于执行环境和作用域,书中没有明确指出作用域和执行环境的异同。执行环境应该指的是上下文环境,和作用域还是有点区别的。例如,函数中,作用域用于定义函数时,上下文环境还包括调用函数时的环境。
当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。当函数执行时,函数内部访问的变量会首先在当前作用域(即作用域链的前端)寻找,如果找不到,则会依次向后寻找,直到找到变量,否则会报错。举个例子:
var color = "red"function getSelfColor() { var color = "yellow" console.log(color)}function getColor() { console.log(color)}getSelfColor()//yellowgetColor()//red
- 在该例子默认的全局环境是window,在该环境中定义了color变量和getSelfColor、getColor两个函数,当getSelfColor和getColor函数被调用时, 会创建该函数环境关联对象的一个作用域链
- window
- color
- getSelfColor
color
- getColor
当getSelfColor执行时,该函数的关联对象推入栈顶,里面定义了color变量,当调用console.log()函数时,优先在当前环境中查找变量,color为yellow。
当getSelfColor执行时,里面没有color变量,当调用console.log()函数时,优先在当前环境中查找变量,因为并没有找到,所以沿作用域链向后查找,color为red。
this
js中的this是个很关键的值,它与函数的执行环境有关。this的值在函数定义时是无法确定的,只有当函数执行时,才能确定this。
window.name = "llx"var a = { name: 'A', fn: function() { console.log(this.name) }}a.fn()a.fn.call({name: 'B'})var fn1 = a.fnfn1()//结果://A//B//llx
js没有块级作用域
js中没有块级作用域,只有函数和全局作用域。即在{}中定义的变量会被添加到当前作用域中,当{}内部的代码被执行完毕以后,并不会销毁变量,因为变量所在的环境的代码并没有被执行完。举例:
if (true) { var color = "red"}console.log(color)//red
此处的{}里面的定义的变量可以被外部访问到,因为里面的部分并不会单独构建新的作用域。
变量提升
在当前作用域的变量定义会被提升到当前环境下代码运行的最前面,这就是javascript的变量提升。举例:
console.log(color)var color = "red"concole.log(color)//结果//undefined//red
第一行的打印并没有报错,就是因为javascript的变量提升机制,代码实际的解释执行是这样的:
var colorconsole.log(color)var color = "red"concole.log(color)
闭包
闭包是指有权访问另一个函数作用域中的变量的函数,闭包的常见形式是在一个函数内部创建另一个函数,一般用来包裹的外层函数是匿名函数。但是闭包并不是指外层的匿名函数。看一个闭包的小例子:
for (var i = 0; i < 10; i ++) { (function(i) { var a = document.createElement('a') a.innerHTML = i + '<br>' a.style.cursor = "pointer" a.addEventListener('click', function(e) { e.preventDefault() alert(i) }) document.body.appendChild(a) })(i) }//例子为创建10个a标签,并且为其添加点击事件,输出a标签的序号
可以看到在上面的例子中,for循环的内部添加一个自执行的函数,并传入变量i,在为a标签绑定事件时,该函数可以获取到上层作用域的变量i,然后打印。
闭包主要用于封装变量,收敛权限。
function isFirstLoad() { var _list = [] return function (id) { if (_list.indexOf(id) >= 0) { return false } else { _list.push(id) return true } } } //使用闭包 var firstLoad = isFirstLoad() console.log(firstLoad(10)) console.log(firstLoad(10)) console.log(firstLoad(20)) //结果 //true //false //true
- JavaScript作用域链和闭包
- JavaScript 作用域和闭包
- javascript 作用域链和闭包
- 细说JavaScript作用域和闭包
- JavaScript作用域和闭包
- 详解javascript作用域和闭包
- javascript作用域和闭包
- javascript作用域和闭包
- javascript作用域和闭包
- JavaScript作用域和闭包
- JavaScript 变量作用域和闭包
- javascript作用域和闭包,this
- Javascript作用域和闭包
- Javascript 的词法作用域、调用对象和闭包
- 浅谈JavaScript的闭包和作用域链
- JavaScript中的作用域链和闭包
- !!JavaScript中的作用域链和闭包 整理
- 精通Javascript 之 作用域和闭包
- 标准电阻阻值速查表及由来
- tyvj 1087 拆分
- ORB SLAM +kinect2 launch
- LinkedList实例
- 扩增子分析QIIME2. 6数据导出Exporting data
- javascript作用域和闭包
- strtotime 获取当前时间的n月前的问题 (不靠谱)
- java8中ForEach Method
- 【JavaScript】事件
- <QNX> Linux Host开发环境搭建
- 面试小结之IO篇
- css-alert-normalize
- python 实现 kNN 算法
- 图片加载框架Picasso源码解析