第五周第三天笔记之面试题解读

面试题解读

1.1 面试题--i++与++i解读

  • 考点:
    • i++在进行运算时,是先进行运算,再加1;++i在运算时,先加1,再进行运算;
    • return的预解释问题:1)return后面的函数定义代码,不进行预解释;2)return下面的代码会进行预解释,但是不会运行;
    • 在复杂的函数嵌套中,考虑私有作用域的释放问题,判断作用域在执行完成后是立即销毁,或是不立即销毁,还是不销毁;
    • 如果当前作用域中找不到变量,去它对应的堆地址的开辟空间寻找(即上级作用域),依次寻找,找不到,会报错;
    • 如何将作用域释放,给其赋值null;
  • 实战题i++
  <script>
      //全局作用域:
      //1.预解释:1)将var fn=xxff00;地址中的内容是字符串;2)var f,只声明;
      //2.执行JS代码:1)f=fn()=xxff00()即变量f的赋值是,xxff00地址中函数调用的结果,赋值结果就是xxff11;则f=xxff11;
      function fn() {
          var i=8;
          return function (n) {
              console.log(n+(i++));
          }
      }//预解释:将var fn=xxff00;地址中的内容是字符串;
      var f=fn();//此时fn()的结果赋给变量f,然后私有作用域被占用,所以fn()形成的私有作用域不释放;如果想让其释放则给其赋值null;即:f=null;
      f(15);//执行xxff11(15)所得的结果,为23;注意的是执行前上级作用域中的i已经变成8;执行后变为9;此时私有作用域属于不销毁状态;
      f(20);//执行xxff11(20)所得的结果,为29;注意的是执行前上级作用域中的i已经变成9;执行后变为10;
      fn()(15);//自执行函数分两步,第一步先执行fn();第二步再执行fn()(15);最后两个私有作用域一起释放(销毁);此时私有作用域属于不立即销毁状态;
      fn()(20);//自执行函数,会重新建立新的私有作用域,然后同时释放;
      fn()(30);
      f(30);//执行xxff11(30)所得的结果,注意的是执行前上级作用域中的i已经变成10;执行后变为11;
     //打印结果依次为:23,29,23,28,38,40
  </script>
i++题分析图
  • 实战题++i
<script>
      function fn() {
          var i=10;
          return function (n) {
              console.log(n+(++i));
          }
      }
      var f=fn();
      f(15);//结果为26,此时i为11;
      f(20);//结果为32,此时i为12;
      fn()(15);//结果为26,两个作用域同时释放;
      fn()(20);//结果31,两个作用域同时释放;
      fn()(30);//结果为41
      f(30);//结果为43;
  </script>
++i题分析图

1.2 面试题-this指向解读

  • 考点:
    • 自执行函数的this指向window,带"."的属性里面的this为"."前面的元素或对象;
    • 普通对象,在堆内存的地址中是以键值对的形式存放的;
    • 私有作用域的释放及上级作用域的查找;
    • 全局属性和私有属性概念;
  <script>
      var num=10;
      var obj={
          num: 20,
          fn:(function (num) {
              this.num*=2;
              num+=10;
              return function () {
                  this.num*=3;
                  num+=1;
                  console.log(num);
              }//return后面的函数定义不进行预解释,返回的是地址,地址中存放的是JS代码字符串;
          })(num)//此时的num为全局属性中的10;自己对象中的num值,如若获取,需要obj.num才能拿到
      };
      var fn=obj.fn;
      fn();//执行结果为:21;
      obj.fn();//执行结果为:22
      console.log(window.num,obj.num);//执行结果为:60,60;
  </script>
this指向题分析图
  • 对象定义阶段解读
    • 考点:对象定义阶段时,会开辟一个空间地址,内容是以键值对形式存在里面,需注意的一点是,当键值对中属性值为自执行函数时,在对象的定义阶段就开始自执行;把执行结果作为属性值赋给对应的属性名;当调用属性值时,就直接赋值,不再执行自执行函数里面的过程;
     <script>
         var num=10;
         var obj={
             num: 20,
             fn:(function (num) {
                 this.num*=2;
                 num+=10;
                 return function () {
                     this.num*=3;
                     num+=1;
                     console.log(num);
                 }//return后面的函数定义不进行预解释,返回的是地址,地址中存放的是JS代码字符串;
             })(num)
         };
         console.log(window.num,obj.num);//结果为:20,20;
     </script>
    
    • 代码解读:在以上代码中,obj全局变量先在预解释中只声明,在执行代码时,进行赋值定义,定义时,会新建一个堆地址,里面放的是键值对,键值对中fn属性名的属性值为自执行函数,当在定义阶段,自执行函数就已经执行完毕,把结果赋给属性名;

1.3 面试题-乘法与++i

  • 考点:上级作用域的查找,全局作用域中i的赋值问题
<script>
    var i=3;
    function fn() {
        i*=2;
        return function (n) {
            console.log(n*(++i));
        }
    }
    var f=fn();
    f(3);//结果为21;
    fn()(3);//结果为45;
    f(4);//结果为64;
    fn()(3);//结果为99;
</script>
分析图1

1.4 面试题-this与||的运用

  • 考点:
    • 1)当函数存在形参但是未赋实参,则形参获得值为undefined;
    • 2)自执行函数的this指向window;函数执行后,没有返回值,返回的是undefined;
    • 3)逻辑运算符"或",可以用作判断,即代码a||b中,只有a为假时才会执行后面的代码,如:var m=a || b;其中a为假,则执行b,此时m赋值为b;
  <script>
      //当函数存在形参但是未赋实参,则形参获得值为undefined;
      var name="圆梦源";
      var age=500;
      name=(function (name,age) {
          //形参赋值:var name="圆梦源"; var age=undefined;
          arguments[0]="圆梦源培训";//即name重新赋值为"圆梦源培训";
          age=age || this.age;
          //重点:当||参与赋值时,判断前面的值是否为false,当为false时,执行||后面的代码
          //此时的this指向为window,则this.age为500;所以age赋值为500;
          console.log(name,age);//结果为"圆梦源培训",500;
      })(name);
      //自执行函数的结果赋给全局作用域中的name,此时自执行函数中没有返回值,所以name赋值为undefined;
      console.log(name,age);//结果为undefined,500;
  </script>
this与或分析图

1.5 实战题

  • 需求:点击div按钮使里面的数字形成自增效果;
  • 思路1:设置全局变量属性;不建议使用,因为会出现全局属性;
    var oDiv=document.getElementsByTagName("div")[0];
    var num=0;//全局属性
    oDiv.onclick=function () {
        this.innerHTML=++num;
    }
  • 思路2:闭包,将全局变量,包裹到私有作用域中,此时就不会存在全局属性;但是会形成不销毁的私有作用域,也不建议;
    • 第一种自执行函数:
         var oDiv=document.getElementsByTagName("div")[0];
          (function () {
                 var num=0;
                 oDiv.onclick=function () {
                 this.innerHTML=++num;
             }
          })();
      
    • 第二种自执行函数:
       var oDiv=document.getElementsByTagName("div")[0];
       oDiv.onclick=(function () {
               //此处的this指向window;
               var num=0;
               return function () {
                   //此处的this指向的是oDiv元素;
                   this.innerHTML=++num;
               }
           })();
           //先执行自执行函数,跟点击事件是否触发无关;实际上点击事件赋值为一个地址,地址中的内容为return后面的函数定义字符串;
      
      this指向分析图
  • 思路3:DOM操作:不建议频繁的进行DOM操作;
  var oDiv=document.getElementsByTagName("div")[0];
  oDiv.onclick=function () {
          this.innerHTML=++this.innerHTML;
      }
  • 思路4:建议:自定义属性;
  var oDiv=document.getElementsByTagName("div")[0];
  oDiv.num=0;//给div元素添加自定义属性;
  oDiv.onclick=function () {
      his.innerHTML=++this.num;
      }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容