争怎路由网:是一个主要分享无线路由器安装设置经验的网站,汇总WiFi常见问题的解决方法。

BAT各大互联网公司javascript前端面试题总结

时间:2024/5/14作者:未知来源:争怎路由网人气:

"操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短路求值。

18.看下列代码,将会输出什么?(变量声明提升)

var foo = 1;
function(){
    console.log(foo);
    var foo = 2;
    console.log(foo);
}

答案:输出undefined 和 2。上面代码相当于:

var foo = 1;
function(){
    var foo;
    console.log(foo); //undefined
    foo = 2;
    console.log(foo); // 2;   
}

函数声明与变量声明会被JavaScript引擎隐式地提升到当前作用域的顶部,但是只提升名称不会提升赋值部分。

19.用js实现随机选取10--100之间的10个数字,存入一个数组,并排序。

var iArray = []; 
funtion getRandom(istart, iend){
        var iChoice = iend - istart +1;
        return Math.floor(Math.random() * iChoice + istart);
}
for(var i=0; i<10; i++){
        iArray.push(getRandom(10,100));
}
iArray.sort();

20.把两个数组合并,并删除第二个元素。

var array1 = ['a','b','c'];
var bArray = ['d','e','f'];
var cArray = array1.concat(bArray);
cArray.splice(1,1);

21.怎样添加、移除、移动、复制、创建和查找节点(原生JS,实在基础,没细写每一步)

1)创建新节点

  • createDocumentFragment() //创建一个DOM片段

  • createElement() //创建一个具体的元素

  • createTextNode() //创建一个文本节点

2)添加、移除、替换、插入

  • appendChild() //添加

  • removeChild() //移除

  • replaceChild() //替换

  • insertBefore() //插入

3)查找

  • getElementsByTagName() //通过标签名称

  • getElementsByName() //通过元素的Name属性的值

  • getElementById() //通过元素Id,唯一性

22.有这样一个URL:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e,请写一段JS程序提取URL中的各个GET参数(参数名和参数个数不确定),将其按key-value形式返回到一个json结构中,如{a:'1', b:'2', c:'', d:'xxx', e:undefined}。

答案:

function serilizeUrl(url) {
    var result = {};
    url = url.split("?")[1];
    var map = url.split("&");
    for(var i = 0, len = map.length; i < len; i++) {
        result[map[i].split("=")[0]] = map[i].split("=")[1];
    }
    return result;
}

23.正则表达式构造函数var reg=new RegExp("xxx")与正则表达字面量var reg=//有什么不同?匹配邮箱的正则表达式?

答案:当使用RegExp()构造函数的时候,不仅需要转义引号(即\"表示"),并且还需要双反斜杠(即\\表示一个\)。使用正则表达字面量的效率更高。

邮箱的正则匹配:

var regMail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/;

24.看下面代码,给出输出结果。

for(var i=1;i<=3;i++){
  setTimeout(function(){
      console.log(i);    
  },0);  
};

答案:4 4 4。

原因:Javascript事件处理器在线程空闲之前不会运行。那么问题来了,如何让上述代码输出1 2 3?

for(var i=1;i<=3;i++){
   setTimeout((function(a){  //改成立即执行函数
       console.log(a);    
   })(i),0);  
};

1           //输出
2
3

25.写一个function,清除字符串前后的空格。(兼容所有浏览器)

使用自带接口trim(),考虑兼容性:

if (!String.prototype.trim) { 
 String.prototype.trim = function() { 
 return this.replace(/^\s+/, "").replace(/\s+$/,"");
 } 
} 

// test the function 
var str = " \t\n test string ".trim(); 
alert(str == "test string"); // alerts "true"

26.Javascript中callee和caller的作用?

答案:

caller是返回一个对函数的引用,该函数调用了当前函数;

callee是返回正在被执行的function函数,也就是所指定的function对象的正文。

那么问题来了?如果一对兔子每月生一对兔子;一对新生兔,从第二个月起就开始生兔子;假定每对兔子都是一雌一雄,试问一对兔子,第n个月能繁殖成多少对兔子?(使用callee完成)

var result=[];
function fn(n){  //典型的斐波那契数列
   if(n==1){
        return 1;
   }else if(n==2){
           return 1;
   }else{
        if(result[n]){
                return result[n];
        }else{
                //argument.callee()表示fn()
                result[n]=arguments.callee(n-1)+arguments.callee(n-2);
                return result[n];
        }
   }
}

中级Javascript:

1.实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制

  • 考察点1:对于基本数据类型和引用数据类型在内存中存放的是值还是指针这一区别是否清楚

  • 考察点2:是否知道如何判断一个变量是什么类型的

  • 考察点3:递归算法的设计

// 方法一:
Object.prototype.clone = function() {
    var o = this.constructor === Array ? [] : {};
    for (var e in this) {
        o[e] = typeof this[e] === "object" ? this[e].clone() : this[e];
    }
    return o;
}

//方法二:
/**
 * 克隆一个对象
 * @param Obj
 * @returns
 */
function clone(Obj) {
    var buf;
    if (Obj instanceof Array) {
        buf = []; //创建一个空的数组 
        var i = Obj.length;
        while (i--) {
            buf[i] = clone(Obj[i]);
        }
        return buf;
    } else if (Obj instanceof Object) {
        buf = {}; //创建一个空对象 
        for (var k in Obj) { //为这个对象添加新的属性 
            buf[k] = clone(Obj[k]);
        }
        return buf;
    } else { //普通变量直接赋值
        return Obj;
    }
}

2.如何消除一个数组里面重复的元素?

var arr = [1, 2, 3, 3, 4, 4, 5, 5, 6, 1, 9, 3, 25, 4];

function deRepeat() {
    var newArr = [];
    var obj = {};
    var index = 0;
    var l = arr.length;
    for (var i = 0; i < l; i++) {
        if (obj[arr[i]] == undefined) {
            obj[arr[i]] = 1;
            newArr[index++] = arr[i];
        } else if (obj[arr[i]] == 1)
            continue;
    }
    return newArr;

}
var newArr2 = deRepeat(arr);
alert(newArr2); //输出1,2,3,4,5,6,9,25

3.小贤是一条可爱的小狗(Dog),它的叫声很好听(wow),每次看到主人的时候就会乖乖叫一声(yelp)。从这段描述可以得到以下对象:

function Dog() {
       this.wow = function() {
               alert(’Wow’);
      }
       this.yelp = function() {
              this.wow();
      }
}

小芒和小贤一样,原来也是一条可爱的小狗,可是突然有一天疯了(MadDog),一看到人就会每隔半秒叫一声(wow)地不停叫唤(yelp)。请根据描述,按示例的形式用代码来实。继承,原型,setInterval

答案:

function MadDog() {
    this.yelp = function() {
          var self = this;          
          setInterval(function() {
                self.wow();      
          }, 500);
      }
}
MadDog.prototype = new Dog();         

//for test
var dog = new Dog();
dog.yelp();
var madDog = new MadDog();
madDog.yelp();

4.下面这个ul,如何点击每一列的时候alert其index?(闭包)

<ul id=”test”>
    <li>这是第一条</li>
    <li>这是第二条</li>
    <li>这是第三条</li>
</ul>

答案:

// 方法一:
var lis=document.getElementById('2223').getElementsByTagName('li');
for(var i=0;i<3;i++)
{
    lis[i].index=i;
    lis[i].onclick=function(){
        alert(this.index);
    };
}

//方法二:
var lis=document.getElementById('2223').getElementsByTagName('li');
for(var i=0;i<3;i++)
{
    lis[i].index=i;
    lis[i].onclick=(function(a){
        return function() {
            alert(a);
        }
    })(i);
}

5.编写一个JavaScript函数,输入指定类型的选择器(仅需支持id,class,tagName三种简单CSS选择器,无需兼容组合选择器)可以返回匹配的DOM节点,需考虑浏览器兼容性和性能。

答案:

var query = function(selector) {
                var reg = /^(#)?(\.)?(\w+)$/img;
                var regResult = reg.exec(selector);
                var result = [];
                //如果是id选择器
                if(regResult[1]) {
                    if(regResult[3]) {
                        if(typeof document.querySelector === "function") {
                            result.push(document.querySelector(regResult[3]));
                        }
                        else {
                            result.push(document.getElementById(regResult[3]));
                        }
                    }
                }
                //如果是class选择器
                else if(regResult[2]) {
                    if(regResult[3]) {
                        if(typeof document.getElementsByClassName === 'function') {
                            var doms = document.getElementsByClassName(regResult[3]);
                            if(doms) {
                                result = converToArray(doms);
                            }
                        }
                        //如果不支持getElementsByClassName函数
                        else {
                            var allDoms = document.getElementsByTagName("*") ;
                            for(var i = 0, len = allDoms.length; i < len; i++) {
                                if(allDoms[i].className.search(new RegExp(regResult[2])) > -1) {
                                    result.push(allDoms[i]);
                                }
                            }
                        }
                    }
                }
                //如果是标签选择器
                else if(regResult[3]) {
                    var doms = document.getElementsByTagName(regResult[3].toLowerCase());
                    if(doms) {
                        result = converToArray(doms);
                    }
                }
                return result;
            }

            function converToArray(nodes){
                  var array = null;         
                  try{        
                        array = Array.prototype.slice.call(nodes,0);//针对非IE浏览器         
                  }catch(ex){
                      array = new Array();         
                      for( var i = 0 ,len = nodes.length; i < len ; i++ ) { 
                          array.push(nodes[i])         
                      }         
                  }      
                  return array;
          }

6.请评价以下代码并给出改进意见。

if(window.addEventListener){
    var addListener = function(el,type,listener,useCapture){
        el.addEventListener(type,listener,useCapture);
  };
}
else if(document.all){
    addListener = function(el,type,listener){
        el.attachEvent("on"+type,function(){
          listener.apply(el);
      });
   }  
}

评价:

  • 不应该在if和else语句中声明addListener函数,应该先声明;

  • 不需要使用window.addEventListener或document.all来进行检测浏览器,应该使用能力检测;

  • 由于attachEvent在IE中有this指向问题,所以调用它时需要处理一下

改进如下:

function addEvent(elem, type, handler) {  
    if (elem.addEventListener) {    
        elem.addEventListener(type, handler, false);  
    } else if (elem.attachEvent) {    
        elem['temp' + type + handler] = handler;    
        elem[type + handler] = function() {    
            elem['temp' + type + handler].apply(elem);  
        };  
        elem.attachEvent('on' + type, elem[type + handler]); 
    } else {  
        elem['on' + type] = handler;  
    }
}

7.给String对象添加一个方法,传入一个string类型的参数,然后将string的每个字符间价格空格返回,例如:

addSpace("hello world") // -> 'h e l l o w o r l d'

String.prototype.spacify = function() {
    return this.split('').join(' ');
};

接着上述答题,那么问题来了

1)直接在对象的原型上添加方法是否安全?尤其是在Object对象上。(这个我没能答出?希望知道的说一下。) 

2)函数声明与函数表达式的区别? 

答案:在Javscript中,解析器在向执行环境中加载数据时,对函数声明和函数表达式并非是一视同仁的,解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问),至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解析执行。(函数声明提升)

8.定义一个log方法,让它可以代理console.log的方法。

可行的方法一:

function log(msg)  {
    console.log(msg);
}
log("hello world!") // hello world!

如果要传入多个参数呢?显然上面的方法不能满足要求,所以更好的方法是:

function log() {
    console.log.apply(console, arguments);
};

那么问题来了,apply和call方法的异同?  

答案:

对于apply和call两者在作用上是相同的,即是调用一个对象的一个方法,以另一个对象替换当前对象。将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

但两者在参数上有区别的。对于第一个参数意义都一样,但对第二个参数: apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。 如 func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3]) 。

9.在Javascript中什么是伪数组?如何将伪数组转化为标准数组?

答案:

伪数组(类数组):无法直接调用数组方法或期望length属性有什么特殊的行为,但仍可以对真正数组遍历方法来遍历它们。典型的是函数的argument参数,还有像调用getElementsByTagName,document.childNodes之类的,它们都返回NodeList对象都属于伪数组。可以使用Array.prototype.slice.call(fakeArray)将数组转化为真正的Array对象。

假设接第八题题干,我们要给每个log方法添加一个"(app)"前缀,比如'hello world!' ->'(app)hello world!'。方法如下:

function log() {
    var args = Array.prototype.slice.call(arguments); //为了使用unshift数组方法,将argument转化为真正的数组
    args.unshift('(app)');

    console.log.apply(console, args);
};

10.对作用域上下文和this的理解,看下列代码:

var User = {
    count: 1,

    getCount: function() {
        return this.count;
    }
};
console.log(User.getCount()); // what?
var func = User.getCount;
console.log(func()); // what?

问两处 console 输出什么?为什么?

答案是 1 和 undefined。

func 是在 winodw 的上下文中被执行的,所以会访问不到 count 属性。

那么问题来了,如何确保Uesr总是能访问到func的上下文,即正确返回1

答案:正确的方法是使用Function.prototype.bind。兼容各个浏览器完整代码如下:

Function.prototype.bind = Function.prototype.bind   

关键词:BAT各大互联网公司javascript前端面试题总结




Copyright © 2012-2018 争怎路由网(http://www.zhengzen.com) .All Rights Reserved 网站地图 友情链接

免责声明:本站资源均来自互联网收集 如有侵犯到您利益的地方请及时联系管理删除,敬请见谅!

QQ:1006262270   邮箱:kfyvi376850063@126.com   手机版