Js基础(二) 作用域链与闭包相关
1、执行上下文
在一段script 或者一个函数作用域中 都会生成一个执行上下文
在全局执行上下文中 js会将 变量 与 函数声明提取出来
在函数执行上下文中 在函数执行之前 会将函数内的变量定义 函数声明 this arguments 提取出来
2、this指向
作为构造函数执行
作为对象属性执行
普通函数执行
call apply bind 方式执行
this只有在执行时才会改变指针 定义时this不会指向任何对象 js是解释型语言不是定义型
3、作用域链
函数作用域链与this恰恰相反 this是只有在执行时候确认 而作用域链是函数在定义时就已经确定了
自由变量 当前函数没有定义的变量叫做自由变量 官方解释: 闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外 上一段代码解释闭包
<script> function fn1(){ var a = 10 return function(){ return a } } var a = 100 var fn = fn1() console.log(fn) console.log(fn()) </script>
上面输出结果是10 也就是说 函数定义的时候其作用域链就已经固定 并且 函数定义时 它的作用域和引用的自由变量就已经固定 无论这个函数 在任何位置引用 调用它内部的自有变量都不会再改变了 理论上说任何一个函数都是一个闭包 那么闭包主要的应用场景就是 保护变量 返回函数 传入函数
function fn1(){ var a = 10 return function(){ return a } } var fn = fn1() function fn2 (fn){ var a = 1000 console.log(fn()) } fn2(fn)
输出结果仍然是10 无论任何环境闭包的作用域和自由变量都已经定死了 下面举两个简单的闭包案例
<script> for(var i = 0; i < 10 ; i++){ (function(i){ var a = document.createElement('a') a.innerHTML = i + '<br/>' a.onclick = function(){ alert(i) } document.body.appendChild(a) })(i) } </script>
上面每次执行我们都创建了一个独立的自执行函数 然后将 i 传入 这个时候自执行函数会将 i 变量固定的保存下来 下面举一个变量权限的例子
function firstIndex(){ var _list = [] return function(id){ if(_list.indexOf(id) >= 0 ){ return false }else{ _list.push(id) return true } } } var fn = firstIndex() console.log(fn(10)) console.log(fn(10)) console.log(fn(20))