作用域和闭包
知识点
- 执行上下文(执行之前拿出来占位即,定义但不赋值)
-
范围:一段
-
全局上下文:变量定义、函数声明
-
函数上下文:变量定义、函数声明、this、arguments(参数)
-
PS:注意”函数声明(
function fn(){})“和”函数表达式(var a = function fn() {})“的区别console.log(a) //undefined var a =100 //变量提升后 a = undefined
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 //this === a
a.fn.call({name: 'B'}) //this === {name: 'B'} //this === {name: 'B'}
var fn1 = a.fn
fn1() //this === window
1、作为构造函数执行
//构造函数
function Foo(name) {
this.name = name
}
var f = new Foo('zhangsan') //this指的是对象
2、作为对象执行
// 作为一个对象属性
var obj = {
name: 'A',
printName: function () {
console.log(this.name) //指obj
}
}
obj.printName()
3、作为普通函数执行
// 普通函数的 this
function fn () {
console.log(this)
}
fn() //window 执行作用域
4、call apply bind
// call apply bind
function fn1(name,age) {
alert(name)
console.log(this)
}
fn1.call({x:100},'zhangsan',20) //使用call 第一项指定this
fn1.apply({x:200},['zhangsan',20]) //使用 apply 第一项指定this ,参数放置在数组中
var fn2 = function (name,age) {
console.log('name',name)
console.log(this)
}.bind({y:300}) //bind在函数后定义this
fn2.('zhangsan',20)
- 作用域
1、JS没有块级作用域
2、只有函数和全局作用域
// 无块级作用域
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) } } var f1 = F1() function F2(fn) { var a = 300 fn() } F2(f1) //100
-
题目
-
说一下对变量提升的理解
- 变量定义
- 函数声明
- 说明this几种不同的使用场景
- 作为构造函数执行
- 作为对象属性执行
- 作为普通函数执行
- call apply bind
-
创建10个标签,点击的时候弹出来对应的序号
var i for(i = 0; i > 10; i++){ (function(i){ var a = document.creatElement('a') a.innerHTML = i + '
' a.addEventListener('click',function (e){ e.preventDefault() alert(i) }) })(i) } -
如何理解作用域
- 自由变量
- 作用域链,即自由变量的查找
- 闭包的两个场景(函数作为参数传递、函数作为返回值)
-
实际开发中闭包的应用
// 闭包实际应用中主要用于封装变量,收敛权限 function is FirstLoad() { 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