饥人谷技术博客

闭包-定时器-BOM

2017-08-08  本文已影响0人  南山码农

题目1: 下面的代码输出多少?修改代码让 fnArri 输出 i。使用 两种以上的方法

var fnArr = [];
for (var i = 0; i < 10; i ++) {
    fnArr[i] =  function(){
        return fnArr.index;
    };
}
console.log( fnArr[3]() );  //10

方法一:

var fnArr = [];
for (var i = 0; i < 10; i ++) {
    (function(i){
        fnArr[i] = function(){
            return i;
        }
    })(i);
}
console.log( fnArr[3]() );  //3

方法二:

var fnArr = [];
for (var i = 0; i < 10; i ++) {
    fnArr[i] =  (function(i){ //IIFE & 闭包
        return function(){
            return i;
        }
    })(i);
}
console.log( fnArr[3]() );  //3

方法三:

var fnArr = [];
for (let i = 0; i < 10; i ++) { //使用ES6: let
    fnArr[i] =  function(){
        return i;
    };
}
console.log( fnArr[3]() );

题目2: 封装一个汽车对象,可以通过如下方式获取汽车状态

var Car = (function(){
  var speed = 0;

  function setSpeed(s){
    speed = s;
  }

  function getSpeed(){
    console.log(speed) ;  
  }
  function accelerate(){
    speed+=10;
  }

  function decelerate(){
     if(speed>10){ 
        speed-=10;
      }else {
         speed = 0;  
    }
  }

  function getStatus(){
      if(speed>0){
      console.log( "running");
      }else{
      console.log("stop") ;
      }
  }

  return {
      setSpeed: setSpeed,
      getSpeed:getSpeed,
      accelerate:accelerate,
      decelerate:decelerate,
      getStatus:getStatus
   }
})()
Car.setSpeed(30);//
Car.getSpeed(); //30
Car.accelerate();//
Car.getSpeed(); //40
Car.decelerate();//
Car.decelerate();//
Car.getSpeed(); //20
Car.getStatus(); // 'running'
Car.decelerate(); //
Car.decelerate();//
Car.getStatus();  //'stop'
Car.speed;  //error

题目3:下面这段代码输出结果是? 为什么?

var a = 1;
setTimeout(function(){
    a = 2;
    console.log(a);
}, 0);
    var a ;
    console.log(a);
    a = 3;
    console.log(a);

输出1 3 2,那是因为setTimeout函数的运行机制是,将制定的代码移出本次执行,等到下一轮EventLoop时,再检查时间,执行代码。这意味着,先console.log(1),再console.log(3),本次代码执行完后再检查时间,执行console.log(2)

题目4:下面这段代码输出结果是? 为什么?

var flag = true;
setTimeout(function(){
    flag = false;
},0)
while(flag){}
console.log(flag);

浏览器会陷入while死循环。因为setTimeout函数的运行机制是,将制定的代码移出本次执行,等到下一轮EventLoop时,再检查时间,执行代码。所以,while循环将一直循环下去,本次EventLoop无法结束,无法进入setTimeout。

题目5: 下面这段代码输出?如何输出delayer: 0, delayer:1...(使用闭包来实现)

for(var i=0;i<5;i++){
    setTimeout(function(i){
         console.log('delayer:' + i );
   }, 0);
    console.log(i);
}

修改后:

for(var i=0;i<5;i++){
  !function(i){
    setTimeout(function(){
         console.log('delayer:' + i );
    }, 0);
  }(i)
}

题目6: 如何获取元素的真实宽高

function getCss(curEle,attr){
      return window.getComputedStyle ? window.getComputedStyle(curEle,null)[attr] : curEle.currentStyle[attr];
}
getCss(ele,'width')//宽度
getCss(ele,'height')//高度

题目7: URL 如何编码解码?为什么要编码?

编码原因:

ps:URI是统一资源标识的意思,通常我们所说的URL只是URI的一种。典型URL的格式如下所示。下面提到的URL编码,实际上应该指的是URI编码。

Paste_Image.png

Url编码的原则就是使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。

解决办法:

三个编码的函数——escape,encodeURI,encodeURIComponent——都是用于将不安全不合法的Url字符转换为合法的Url字符表示,它们有以下几个不同点。
  安全字符不同:
  下面列出了这三个函数的安全字符(即函数不会对这些字符进行编码)

兼容性不同:escape函数是从Javascript 1.0的时候就存在了,其他两个函数是在Javascript 1.5才引入的。但是由于Javascript 1.5已经非常普及了,所以实际上使用encodeURI和encodeURIComponent并不会有什么兼容性问题。

对Unicode字符的编码方式不同:这三个函数对于ASCII字符的编码方式相同,均是使用百分号+两位十六进制字符来表示。但是对于Unicode字符,escape的编码方式是%uxxxx,其中的xxxx是用来表示unicode字符的4位十六进制字符。这种方式已经被W3C废弃了。但是在ECMA-262标准中仍然保留着escape的这种编码语法。encodeURI和encodeURIComponent则使用UTF-8对非ASCII字符进行编码,然后再进行百分号编码。这是RFC推荐的。因此建议尽可能的使用这两个函数替代escape进行编码。

适用场合不同:encodeURI被用作对一个完整的URI进行编码,而encodeURIComponent被用作对URI的一个组件进行编码。从上面提到的安全字符范围表格来看,我们会发现,encodeURIComponent编码的字符范围要比encodeURI的大。我们上面提到过,保留字符一般是用来分隔URI组件(一个URI可以被切割成多个组件,参考预备知识一节)或者子组件(如URI中查询参数的分隔符),如:号用于分隔scheme和主机,?号用于分隔主机和路径。由于encodeURI操纵的对象是一个完整的的URI,这些字符在URI中本来就有特殊用途,因此这些保留字符不会被encodeURI编码,否则意义就变了。

题目8: 补全如下函数,判断用户的浏览器类型

function isAndroid(){
    return /android/i.test(navigator.userAgent);
}
function isIphone(){
    return /iphone/i.test(navigator.userAgent);
}
function isIpad(){
    return /ipad/i.test(navigator.userAgent);
}
function isIOS(){
    return /iphone|ipad/i.test(navigator.userAgent);
}
上一篇下一篇

猜你喜欢

热点阅读