题目:
- 说一下对变量提升的理解:变量定义&函数声明(注意和函数表达式的区别)
- 说明this几种不同的使用场景:构造函数&对象属性&普通函数&call apply bind
- 用js创建10个<a>标签,点击的时候弹出对应的序号
var i
for(i = 0; i < 10; i++){
(function(i){
var a = document.creatElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click',function(e){
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
})(i) //自执行函数 将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))//true
console.log(firstLoad(10)) //false
firstLoad(20) //true
firstLoad(20) //false
// 目的:在 isFirstLoad 函数外面,不可能改掉 _list 的值
知识点:
- 执行上下文
- this
- 作用域
- 作用域链
- 闭包
1. 执行上下文
- 范围:一段<script>或者一个函数
- 全局执行上下文(一段<script>):变量定义、函数声明,都提声
- 函数执行上下文(一个函数):变量定义、函数声明、this、arguments
<script>
console.log(a)
var a = 100 //变量定义,实际不要这么写
fn('zhangsan') // 'zhangsan' 20
function fn(name){ //函数声明
age = 20 //所以age在这里没有关系
console.log(name,age)
var age
}
</script>
ps:函数声明与函数表达式的区别
fn();//不报错
function fn(){
//声明
}
fn1();//报错
var fn1 = function (){
//表达式
}
2. 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
四种情况:
- 作为构造函数执行
- 作为对象属性执行
- 作为普通函数执行
- call apply bind 函数
//构造函数
function Foo(name){
//this = {}
this.name = name
//return this
}
var f = new Foo('zhangsan') //牵扯到new一个对象的过程
//对象
var odj = {
name:'A',
printName: function(){
console.log(this.name)
}
}
obj.printName() //this就是obj对象
//普通函数
function fn(){
console.log(this) //this === window
}
fn()
// call apply bind
function fn1(name){
alert(name)
console.log(this)
}
fn1.call({x:100},'zhangsan',20) //this :{x:100} jQuery经常用call来改变this值
//对于bind来说,可以这样使用
var fn2 = function(name,age){ //函数表达式才能用.bind 函数声明会报错
console.log(this)
}.bind({y:200}) //this从window变为{y:200}
fn2('zhangsan',20)
3. 作用域
- 没有块级作用域
- 只用函数和全局作用域
//无块级作用域
if(ture){
var name = 'zhangsan'
}
console.log(name) //java会报错,因为变量出不了{},但是js不会,但是程序不易读还是尽量不要在块里声明变量
//函数和全局作用域
var a = 100
function fn(){
var a = 200
console.log('fn',a) //200
}
console.log('global',a) //100
fn()
4. 作用域链
- 自由变量:当前作用域没有定义的变量,即“自由变量”
- 作用域链:一个自由变量一直不断的向父级作用域去找,形成一个链式结构
var a = 100
function fn(){ //这个函数的父级作用域是全局作用域
var b = 200
//a:当前作用域没有定义的变量,即“自由变量”
console.log(a)
console.log(b)
}
fn()
//函数的父级作用域是函数定义的时候被定义的时候被调用的,不是函数执行的时候
5. 闭包
闭包的使用场景:
- 函数作为返回值
- 函数作为参数传递
//1.函数作为返回值
function F1(){
var a = 100
//返回一个函数
return function(){
console.log(a) //a是自由变量,上父级作用域
}
}
//f1得到一个函数
var f1 = F1()
var a = 200
f1() //100 重申:是定义时候的作用域 而非执行时候的
//2.函数作为参数
function F1(){
var a = 100
//返回一个函数
return function(){
console.log(a) //a是自由变量,上父级作用域
}
}
var f1 = F1()
function F2(fn){
var a = 200
fn() //作用域去定义的地方找
}
F2(f1)