原生js面试题

 六、对闭包的看法,为什么要用闭包?说一下闭包的原理以及应用场景?闭包的 this 指向问题

闭包的作用:
1. 在外部访问函数内部的变量
2. 让函数内的局部变量可以一直保存下去
3. 模块化私有属性和公共属性

闭包的原理:
全局变量生存周期是永久,局部变量生存周期随着函数的调用介绍而销毁。
闭包就是 在函数中定义且成为该函数内部返回的函数的自由变量 的变量,该变量不会随着外部函数调用结束而销毁。 
(注:不光是变量,函数内声明的函数也可以形成闭包)
当函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行,这时就产生了闭包。

闭包的应用场景

// 1. 返回值 最常见的一种形式

    var fun_1 = function () {
      var name = "limo";
      return function () {      
        return name;
      }
    }
    var fun_1 = function () {
      var name = "limo";
      return name;
    }
    var fu_1 = fun_1();
    console.log("fu_1():" + fu_1());

// 2. 函数赋值 一种变形的形式是将内部函数赋值给一个外部变量

    var f2;
    var fun_2 = function () {
      var name = "limop"
      var a = function () {
        return name;
      }
      f2 = a;
    }
    f2();
    console.log(f2);

// 3. 函数参数 通过函数参数引用内部函数产生闭包

    var fn_3 = function (f3) {
      console.log(f3);
    }

    function fun_3() {
      var name = "limo";
      var a = function () {
        return name;
      }
      fn_3(a)
    }
    fun_3();

// 4. IIFE(自执行函数)

    var fn_4 = function (f4) {
      console.log(f4);
    };
    (function fun_4() {
      var name = "limo";
      var a = function () {
        return name;
      }
      fn_3(a)
    })();

// 5. 循环赋值

    function foo(){
      var arr = [];
      for(var i = 0; i < 10; i++){
        arr[i] = (function(n){
          return function(){
            return n;
          }
        })(i)
      }
      return arr;
    }
    var bar = foo();
    console.log(bar[3]());

// 6. getter和setter

    // getter和setter函数来将要操作的变量保存在函数内部,防止暴露在外部
    var getValue, setValue;
    (function () {
      var num = 0
      getValue = function () {
        return num
      }
      setValue = function (v) {
        if (typeof v === 'number') {
          num = v
        }
      }
    })();
    console.log(getValue());    //0
    setValue(10);
    console.log(getValue())     //10

// 7.迭代器(计数器)

    var add = function(){
      var num = 0;
      return function(){
        return ++num;
      }
    }();
    console.log(add());
    console.log(add());

    function setUp(arr){
      var i = 0;
      return function(){
        return arr[i++];
      }
    }
    var next = setUp(['Steve','Alex','LingYi']);
    console.log(next());
    console.log(next());
    console.log(next());

// 8.触发事件

    window.onload = function (){
      var btn = document.querySelector('.btn')
      btn.onclick = function (){//事件相当于在全局触发
        btn.style.color = 'red'//保持对上层作用域的引用 btn
        console.log('abc')
        // this
      }
    }

闭包的this指向问题:

var myNumber = {
  value: 1,
  add: function(i){
    var helper = function(i){
        console.log(this);
          this.value += i;
    }
    helper(i);
  }
}
myNumber.add(1);
1.this指向window对象(因为匿名函数的执行具有全局性,所以其this对象指向window);
2.不能实现value加1(每个函数在被调用时都会自动取得两个特殊变量,this和arguments,内部函数在搜索这两个对象时,只会搜索到其活动对象为止,所以不能实现访问外部函数的this对象);
3.修改代码实现正确功能

第一种解决方法:

var myNumber={
    value:1,
    add:function(i){
        var that=this;//定义变量that用于保存上层函数的this对象
        var helper=function(i){
             console.log(that);
        that.value+=i;
    }
    helper(i);
    }
}
myNumber.add(1);

第二种解决方法:

var myNumber={
    value:1,
    add:function(i){
        var helper=function(i){
            this.value+=i;
        }
        helper.apply(this,[i]);//使用apply改变helper的this对象指向,使其指向myNumber对象
    }
}
myNumber.add(1);
第三种解决方法

var myNumber={
    value:1,
    add:function(i){
        var helper=function(i){
            this.value+=i;
        }.bind(this,i);//使用bind绑定,和apply相似,只是它返回的是对函数的引用,不会立即执行
        helper(i);
    }
}
myNumber.add(1);

  七、简述闭包的问题以及优化

闭包的缺点:占用内层空间 大量使用闭包会造成 栈溢出

由于闭包会一直占用内存空间,直到页面销毁,我们可以主动将已使用的闭包销毁:
将闭包函数赋值为null 可以销毁闭包

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值