先抛出几个问题:
- 说一下对变量提升的理解
- 说明this的几种不同使用场景
- 如何理解作用域?
- 实际开发中闭包的应用?
- 用JS创建10个
<a>标签,点击的时候弹出对应的序号?
作用域
- JS没有块级作用域
- 只有函数和全局作用域
//无块级作用域
if(true){
var name = 'zhangshan'
}
console.log(name) //'zhangshan'
//函数和全局作用域
var a = 100
function fn () {
var a = 200
console.log('fn',a)
}
console.log('global',a) // 'global', 100
fn() // 'fn', 200
作用域链
var a = 100
function F1 () {
var b = 200
function F2() {
var c = 300
// 当前作用域没有定义的变量,即“自由变量”
console.log(a) // a 是自由变量
console.log(b) // c 是自由变量
console.log(c)
}
F2()
}
F1()
执行上下文
- 范围:一段
- 全局:变量定义、函数声明 (一段
- 函数:变量定义、函数声明、this、arguments (函数)
console.log(a) //undefined (变量提升)
var a = 100
fn('zhangshan') //'zhangshan' 20
function fn(name) {
age = 20
console.log(name, age)
var age
}
PS: 注意函数声明和函数表达式的区别
fn() // undefined
function fn() {
// 函数声明
}
fn1() // Uncaught TypeError: fn1 is not a function
var fn1 = function() {
// 函数表达式
}
this
- 在执行时才能确认值,定义时无法确认
var a = {
name: 'A',
fn: function () {
console.log(this.name)
}
}
a.fn(); // A
a.fn.call({name: 'B'}) // B
var fn1 = a.fn
fn1() // undefined
- 作为构造函数执行
- 作为对象属性执行
- 作为普通函数执行
- call apply bind
// 作为构造函数执行
function Foo (name) {
// this = {}
this.name = name
// return this
}
var f = new Foo('zhangshan')
//作为对象执行
var obj = {
name: 'A',
printName: function () {
console.log(this.name)
}
}
obj.printName() // 'A'; this 指向 obj
//作为普通函数执行
function fun () {
console.log(this)
}
fun() // this === window
// call
function fn1(name,age) {
alert(name) // zhangshan
console.log(this) // {x:100};
}
fn1.call({x:100,},'zhangshan',20) // this === {x:100}
// apply
function fn2(name,age) {
alert(name)
console.log(this) // {x:100};
}
fn2.apply({x:100,},['zhangshan',20]) // this === {x:100}
// bind
var fn3 = function (name,age) {
alert(name)
console.log(this) // {y:200};
}.bind({y:200})
fn3('zhangshan',20) // this === {y:200}
闭包
先看一个例子
function F1 () {
var a = 100
// 返回一个函数(函数作为返回值)
return function() {
console.log(a)
}
}
// f1 得到一个函数
var f1 = F1()
var a = 200
f1()
闭包的应用
- 函数作为返回值
- 函数作为参数传递
// 函数作为返回值
function F1() {
var a = 100
//返回一个函数(函数作为返回值)
return function() {
console.log(a) //a作为自由变量,去父作用域寻找
}
}
var f1 = 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 = 200
fn()
}
F2(f1) //100
如何理解作用域
- 自由变量
- 作用域链,即自由变量的查找
- 闭包的2个场景 闭包在实际开发中的应用
// 闭包在实际应用中主要用于封装变量,收敛权限
function isFisrtLoad() {
var _list = []
return function (id){
if(_list.indexOf(id) >=0 ){
return false
} else {
_list.push(id)
return true
}
}
}
// 使用
var firstLoad = isFisrtLoad()
firstLoad(10) // true
firstLoad(10) // false
firstLoad(20) // true
创建10个<a>标签 点击的时候弹出对应的序号
//错误写法
var i, a
for (i = 0; i < 10; i++) {
a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click', function(e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(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)
}