作用域和闭包
-
对变量提升的理解
- 变量定义
- 函数声明(注意和函数表达式的区别)
-
说明 this 几种不同的使用场景
-
创建 10 个
<a>
标签,点击的时候弹出对应的序号var i for (i = 0; i < 10; i++) { ;(function(i) { var a = document.createElement('a') a.innerHTML = i + '<br>' a.addEventListener('click', function(e) { e.preventDefault() alert(i) // 自由变量,要去父作用域获取值 }) document.body.appendChild(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() firstLoad(10) //true firstLoad(10) //false firstLoad(20) //true firstLoad(20) //false //你在isFirstLoad函数外面,不可能修改_list的值
知识点
-
执行上下文
-
范围:一段
<script>
或者一个函数 -
全局:变量定义、函数声明 一段
<script>
-
函数:变量定义、函数声明、this、arguments 函数
-
PS:注意"函数声明"和"函数表达式"的区别
console.log(a) //undefined //下一行为函数表达式 var a = 100 fn('zhangsan') //'zhangsan' 20 //以下为函数声明 function fn(name) { age = 20 console.log(name, age) var age }
-
-
this
-
this 要在执行时才能确认值,定义时无法确认
var a = { name: 'A', fn: function() { console.log(this.name) } } //上面是定义时,下一行为执行时 a.fn() //this === a a.fn.call({ name: 'B' }) //this ==={name:'B'} var fn1 = a.fn fn1() //this === window
-
作为构造函数执行
function Foo(name) { this.name = name } var f = new Foo('zhangsan')
-
作为对象属性执行
var obj = { name = 'A', printName: function(){ console.log(this.name); } } obj.printName();
-
作为普通函数执行
function fn() { console.log(this) //this === window } fn()
-
call、apply、bind
说明:call ()和 apply()作用一样,但是 call()可以接收任何类型的参数,而 apply()只能接收数组参数。//call function fn1(name, age) { alert(name) console.log(this) //this为{x:100} } fn1.call({ x: 100 }, 'zhangsan', 20) //apply function fn2(name, age) { alert(name) console.log(this) //this为{x:100} } fn2.apply({ x: 100 }, ['zhangsan', 20]) //bind var fn3 = function(name, age) { alert(name) console.log(this) //this为{y:200} }.bind({ y: 200 }) fn3('zhangsan', 20)
-
-
作用域
-
没有块级作用域
if (true) { var name = 'zhangsan' } console.log(name)
-
只有函数和全局作用域
var a = 100 function fn() { var a = 200 console.log('fn', a) } console.log('global', a) fn()
-
作用域链
var a = 100 function fn() { var b = 200 //当前作用域没有定义的变量,即"自由变量" console.log(a) console.log(b) } fn()
var a = 100 function F1() { var b = 200 function F2() { var c = 300 console.log(a) //a是自由变量 console.log(b) //b是自由变量 console.log(c) } F2() } F1()
-
-
闭包
-
函数作为返回值
function F1() { var a = 100 //返回一个函数(函数作为返回值) return function() { console.log(a) } } //f1得到一个函数 var f1 = F1() var a = 200 f1() //100
-
函数作为参数传递
function F1() { var a = 100 //返回一个函数(函数作为返回值) return function() { console.log(a) //自由变量,父作用域寻找 } } //f1得到一个函数 var f1 = F1() function F2(fn) { var a = 200 fn() } F2(f1) //100,a的值跟执行作用域无关,与声明作用域有关
-