前端面试题(JavaSscipt 作用域和闭包)

141 阅读3分钟

作用域和闭包

知识点

  • 执行上下文(执行之前拿出来占位即,定义但不赋值)
  1. 范围:一段

  2. 全局上下文:变量定义、函数声明

  3. 函数上下文:变量定义、函数声明、this、arguments(参数)

  4. 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

  • 题目

  • 说一下对变量提升的理解

  1. 变量定义
  2. 函数声明
  • 说明this几种不同的使用场景
  1. 作为构造函数执行
  2. 作为对象属性执行
  3. 作为普通函数执行
  4. call apply bind 
  1. 自由变量
  2. 作用域链,即自由变量的查找
  3. 闭包的两个场景(函数作为参数传递、函数作为返回值)
  • 实际开发中闭包的应用

    // 闭包实际应用中主要用于封装变量,收敛权限 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