前端开发面试题总结之——JAVASCRIPT(三)


相关知识点

数据类型、运算、对象、function、继承、闭包、作用域、原型链、事件、RegExp、JSON、Ajax、DOM、BOM、内存泄漏、跨域、异步加载、模板引擎、前端MVC、前端MVVM、路由、模块化、Http、Canvas、jQuery、ECMAScript 2015(ES6)、Node.js、AngularJS、Vue、React......

题目&答案

  • 函数记忆,判断是不是质数.
方法一:
function isPrime1(num){
    // 不是数字或者数字小于2
    if(typeof num !== "number" || !Number.isInteger(num)){      // Number.isInterget 判断是否为整数
        return false;
    }
    //2是质数
    if(num == 2){
        return true; 
    }else if(num % 2 == 0){  //排除偶数
        return false;
    }
    //依次判断是否能被奇数整除,最大循环为数值的开方
    var squareRoot = Math.sqrt(num);
    //因为2已经验证过,所以从3开始;且已经排除偶数,所以每次加2
    for(var i = 3; i <= squareRoot; i += 2) {
      if (num % i === 0) {
         return false;
      }
    }
    return true;
}
方法二:hash
    var isPrime2=(function(){//hash
      var hash={};
      return function(n){
        if(n<=3){return true}
        else if(hash[n]!==undefined){
          return hash[n];
        }else{
          for(var i=2;i<Math.sqrt(n);i++){
            if(n%i==0){return hash[n]=false}
          }
          return hash[n]=true;
        }
      }
})();
  • 数组去重
方法一:
var arr1=[1,2,3,2,1,2];
    function repeat1(arr){
      for(var i=0,arr2=[];i<arr.length;i++){
        if(arr2.indexOf(arr[i])==-1){
          arr2.push(arr[i]);
        }
      }//(遍历结束)
      return arr2;
}
方法二:hash
function repeat2(arr){
      //遍历arr中每个元素,同时声明hash
      for(var i=0,hash={};i<arr.length;i++){
       //hash中是否包含当前元素值的建
    //如果不包含,就hash添加一个新元素,以当前元素值为key,value默认为1
        if(hash[arr[i]]===undefined){
          hash[arr[i]]=1;
        }
      }//(遍历结束)
      //将hash转为索引:
      var i=0;
      var arr2=[];
      for(arr2[i++] in hash);
      return arr2;
}
方法三:
function repeat3(arr){
      return arr.sort()
               .join(",,")
               .replace(
                /(^|,,)([^,]+)(,,\2)*/g,
                "$1$2")
               .split(",,");
    }
 console.log(repeat3(arr1));
  • 插入排序
var arr=[2,4,1,5,3];
    function insertSort(arr){
      //遍历arr中每个元素(i从1开始)
      for(var i=1;i<arr.length;i++){
        //将当前元素临时保存在变量t中
        var t=arr[i];
        var p=i-1;//声明变量p=i-1
        //循环:(arr[p]>t&&p>=0){
        while(arr[p]>t&&p>=0){
       //将p位置的值,赋值给p+1位置
          arr[p+1]=arr[p];
          p--;//p--
        }//(循环结束)
        arr[p+1]=t;//将t放在p+1的位置上
      }//(循环结束)
    }
    insertSort(arr);
console.log(String(arr));
  • 快速排序:
    function quickSort(arr){
      //如果arr的length<=1
      if(arr.length<=1){
        return arr;//就直接返回arr
      }
      //计算参照位p
      var p=Math.floor(arr.length/2);
      var left=[];
      var right=[];
      //删除p位置的元素
      var center=arr.splice(p,1)[0];
      //遍历arr中每个元素
      for(var i=0;i<arr.length;i++){
        if(arr[i]>=center){
          right.push(arr[i]);
        }else{
          left.push(arr[i]);
        }
      }
      return quickSort(left) .concat(center,quickSort(right))
    }
    var sortedArr=quickSort(arr);
    console.log(String(sortedArr));
  • 正则表达式
(1) "ryan5 is6 not7 a8 good9 man10"
var n=5;
var str="ryan is not a good man";
str=str.replace(/\b[a-z]+\b/g,function(kw){ return kw+n++;});
console.log(str);
  • 统计字符串中每种字符出现的次数,出现次数最多的是? 出现?次
    var str="helloworld";
    方法一:用hash
    for(var i=0,hash={};i<str.length;i++){
      if(hash[str[i]]){
        hash[str[i]]++
      }else{
        hash[str[i]]=1;
      }
    }
    console.dir(hash);
方法二:用正则
var arr=str.split("")
    .sort()
    .join("")
    .match(/([a-z])\1*/g)
    .sort(function(a,b){
return b.length-a.length; })
console.log("出现最多的是: "+arr[0][0]
    +"共"+arr[0].length+"次");
var hash={};
    arr.forEach(function(val){
      hash[val[0]]=val.length;
    });
    console.dir(hash);
  • 数组降维
var arr=[
      [0,0,0,0],
      [0,0,0,0],
      [0,0,0,0],
      [0,0,0,0],
    ];
    //method 1:
    for(var r=0,arr1=[];r<arr.length;r++){
      for(var c=0;c<arr[r].length;c++){
        arr1.push(arr[r][c]);
      }
    }
    console.dir(arr1);
    //method 2: 
    for(var r=0,arr2=[];r<arr.length;r++){
      arr2=arr2.concat(arr[r]);
    }
    console.dir(arr2);
  //method 3:
    var arr2=[].concat.apply([],arr);
    console.dir(arr2);
  • Function赋值
    var f=function(){var a=b=1;}
    f();
    console.log(b);//1
    console.log(a);//报错
    var f=function(){var a=b=1;}
    setTimeout(f,0);
    console.log(b);//报错
    f();
    var a,b=0, fn=function(){var a=b=2;}
    fn();
    console.log(a);//undefined
    console.log(b);//2
  • 函数currying(柯里华)
    var getN;
    function add(n){
      getN=function(){console.log(n);}
      return function(m){
        n+=m;
      arguments.callee.toString=function(){
          return n;
        }
        return arguments.callee;
      }
    }
    add(1)(2)(3); getN();//6
    add(1)(2)(3)(4); getN();//10
    alert(add(1)(2)(3));//6
    alert(add(1)(2)(3)(4));//10
  • 递归
var emp={
   work:function(){//3,2,1
    var  sum=0;//+3+2+1 +2+1  +1
    for(vari=0; i<arguments.length&&arguments[0]>0;
          i++){
          sum+=arguments[i]
              +arguments.callee(
                --arguments[i]
              );
        }
        return sum;
      }
    }
    console.log(emp.work(3,2,1));//10
  • 闭包
(1)function fun(n,o){//外层函数
      console.log(o);
      return {
        fun:function(m){//内层函数 n
          return fun(m,n);
        }
      }
    }
    var a=fun(0);a.fun(1); a.fun(2); a.fun(3);
     //undefined  0      0       0
var a=fun(0).fun(1).fun(2).fun(3);
//undefined   0    1    2
var a=fun(0).fun(1); a.fun(2); a.fun(3);
//undefined  0       1      1
(2)var a=0,b=0;
    function A(a){
      A=function(b){alert(a+b++)};
      alert(a);
    }
    A(1);//1
    A(12);//13
  • OOP
(1)
window.a=300;
    function fn1(){
      this.a=100;
      this.b=200;
      return function(){
                alert(this.a)
              }.call(arguments[0])
    }
    function fn2(){ this.a=new fn1(); }
var a=new fn1().b;//300
var v=new fn1(fn2());//[object Object]
(2)
var number=2;//4  8
    var obj={
      number:4,//8
      fn1:(function(){
        //var number;
        this.number*=2;
number*=2; //声明提前  undefined
        var number=3;
        return function(){
          this.number*=2;
          number*=3;
          alert(number);
        }
      })()
    }
    var fn1=obj.fn1;
    alert(number); fn1(); obj.fn1(); 
    //4           9      27
    alert(window.number);//8
    alert(obj.number);//8
(3)
function Foo(){
    getName=function(){alert(1);};
      return this;
  }
  Foo.getName=function(){alert(2);};
  Foo.prototype.getName=function(){
    alert(3);
  };
  var getName=function(){alert(4);};
  function getName(){ alert(5); };
  Foo.getName();//2
  getName();//4
  Foo().getName();//1
  getName();//1
  new Foo.getName();//2
  new Foo().getName();//3
  new new Foo().getName();//3
(4)
  var a=1;
  var b={
    a:2,
    b:function(){
      console.log(this.a);//1
    }(), 
    f:this.f=function(){
      console.log(this.a);
    }
  };
  function f(){ console.log(3); }
  f();//1
  b.f();//2
  (b.f)();//2
  (0,b.f)();//1
(5)
  var foo=function(){
    console.log(this.a);
  }
  var obj={a:2,foo:foo};
  var a=10;
  var bar=obj.foo;
  var bar2=foo.bind(obj);
  bar();//10
  bar2();//2
  foo();//10
  obj.foo();//2
  setTimeout(bar,0);//10
(6)
function MyObj(){ 
    this.p.pid++; 
  }
  MyObj.prototype.p={"pid":0}//2
MyObj.prototype.getNum=function(num){
    return this.p.pid+num;
  }
  var _obj1=new MyObj(); //创建新对象,继承原型pid+1
  var _obj2=new MyObj(); //创建新对象,继承原型pid+2
  console.log(
    _obj1.getNum(1)+_obj2.getNum(2)
  );//7      2+1   +    2+2
  • 判断一个对象是不是数组类型,有五种方法:
(1) typeof 无法判断 只能判断原始类型的值和函数
(2)isPrototypeOf 判断父及对象   可检查整个原型链 //可能继承自数组
    console.log(Array.prototype.isPrototypeOf([])?"是数组":"不是数组");
    console.log(Array.prototype.isPrototypeOf({})?"是数组":"不是数组");
    console.log(Array.prototype.isPrototypeOf(function(){})?"是数组":"不是数组");�
(3)constructor 检查指定对象的构造函数 可检查整个原型链  //可能继承自数组
    var father={};
    var son={};
    father.__proto__=Array.prototype;
    son.__proto__=father;
    console.log(son.contructor==Array?"是数组":"不是数组")
    console.log({}.contructor==Array?"是数组":"不是数组");
    console.log(function(){}.contructor==Array?"是数组":"不是数组");�
(4)instanceof 检查一个对象是否是制定构造函数的实例 可检查整个原型链 //可能继承自数组
    var father={};
    var son={};
    father.__proto__=Array.prototype;
    son.__proto__=father;
    console.log(son instanceof Array?"是数组":"不是数组");
    console.log({} instanceof Array?"是数组":"不是数组");
    console.log(function(){} instanceof Array?"是数组":"不是数组");
(5)强行用要检查的对象,调用原始的toString方法  不检查整个原型链
        //[object class]: class-Array Date Object
        //只能检查最初就是数组创建的对象。
        console.log(Object.prototype.toString.call([])=="[object Array]"?"是数组":"不是数组");
        console.log(Object.prototype.toString.call({}));
        console.log(Object.prototype.toString.call(function(){}));
        console.log(Object.prototype.toString.call(/\d/));
        var father={};
         var son={};
         father.__proto__=Array.prototype;
         son.__proto__=father;
        console.log(Object.prototype.toString.call(son)=="[object Array]"?"是数组":"不是数组");//不是
        //结论: 对象一旦创建,class属性就无法修改
               //修改继承关系,也无法修改class属性
(6) Array.isArray(obj)  不检查整个原型链
        console.log(Array.isArray([]));
        console.log(Array.isArray({}));
    //如果浏览器不支持isArray
    if(Array.prototype.isArray===undefined){//if(!Array.isArray)
        //给?添加isArray方法
        Array.prototype.isArray=function(arg){
            //强行调用原始toString方法,和"[object Array]"比较
            return Object.prototype.toString.call(arg)
            =="[object Array]"?"是数组":"不是数组";
        }
    }
  • 自定义Object.create()——手写
    Object.create=function(father,props){
        console.log("我的create");
        /*使用setPrototypeOf方法
        var o=Object();//1. 创建空对象
        Object.setPrototypeOf(o,father);//2. 继承father
        */
        /*不使用setPrototypeOf方法
        function Constructor(){}
        Constructor.prototype=father;
        var o=new Constructor();
        */
        Object.defineProperties(o,props);//3. 定义新属性
        return o;
    }
  • 深克隆原理
Object.clone=function(obj){//深克隆
if(typeof(obj)=="object"){//如果obj是对象
    var o=//有必要区分数组和普通对象
    Object.prototype.toString.call(obj)=="[object Array]"?[]:{};
        for(var key in obj){//遍历obj的自有属性
            //如果key是obj的自有属性
            if(obj.hasOwnProperty(key)){
                o[key]=arguments.callee(obj[key]);//arguments.callee调的是当前的Object.clone函数
                }
        }
        return o;
        }else{//如果obj是原始类型的值,就直接返回副本
            return obj;
        }
    }
  • 如果浏览器不支持every属性,every的实现原理
    if(Array.prototype.every===undefined){
       Array.prototype.every=function(fun){
        //遍历当前数组中每个元素
        for(var i=0;i<this.length;i++){
            if(this[i]!==undefined){
//调用fun,依次传入当前元素值,位置i,当前数组作为参数  ,将返回值,保存在变量r中
            var r=fun(this[i],i,this);
            if(r==false){//如果r为false
               return false;//返回false
            }
            }
             }//(遍历结束)
         return true;//返回true
       }
    }
  • 如果浏览器不支持some属性,some的实现原理
    if(Array.prototype.some===undefined){
       Array.prototype.some=function(fun){
          for(var i=0;i<this.length;i++){
          if(this[i]!==unefined){
            var r=fun(this[i],i,this);
                if(r==true){ return true; }
                  }
              }
          return false;
       }    
    }
  • 浏览器不支持map属性,map的实现原理
    if(Array.prototype.map===undefined){
       Array.prototype.map=function(fun){
        //创建空数组: newArr
        var newArr=[];
        //遍历当前数组中每个元素
        for(var i=0;i<this.length;i++){
           //如果当前元素不是undefined
           if(this[i]!==undefined){//判断稀疏数组
//调用fun传入当前元素值,位置i,当前数组,将结果保存在r中
                //将newArr的i位置赋值为r
            var r=fun(this[i],i,this);
                    newArr[i]=r;
           }
        }//(遍历结束)
        return newArr;//返回newArr
       }
    }
  • 如果浏览器不支持reduce属性,reduce的实现原理
    if(Array.prototype.reduce===undefined){
       Array.prototype.reduce=function(fun,base){
         base===undefined&&(base=0);
         for(var i=0;i<this.length;i++){
        if(this[i]!==undefined){
           base=fun(base,this[i],i,this);
        }
             }
         return base;
           }
    }
  • 如果浏览器不支持bind属性, bind函数的实现原理
       if(Function.prototype.bind===undefined){
       Function.prototype.bind=function(obj/*,参数列表*/){
        var fun=this;//留住this
                //*****将类数组对象,转化为普通数组
        var args=Array.prototype.slice.call(arguments,1);
        //args保存的就是提前绑定的参数列表
        /*function slice(1){
           var sub=[];
           for(var i=0;i<length;i++){
            sub.push(arguments[i]);
           }
           return sub;
        }*/
        return function(){
                   //将后传入的参数值,转为普通数组      
           var innerArgs=Array.prototype.slice.call(arguments);//将之前绑定的参数值和新传入的参数值,拼接为完整参数之列表
           var allArgs=args.concat(innerArgs)
          //调用原始函数fun,替换this为obj,传入所有参数
          fun.apply(obj,allArgs);
        }
       }
    }

相关系列:
前端开发面试题总结之——HTML
前端开发面试题总结之——CSS3
前端开发面试题总结之——JAVASCRIPT(一)
前端开发面试题总结之——JAVASCRIPT(二)

以上所有资料来源网络,如有不对的地方希望及时告知,谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 如何控制alert中的换行?\n alert(“p\np”); 请编写一个JavaScript函数 parseQu...
    heyunqiang99阅读 1,083评论 0 6
  • Javascript有很多数组的方法,有的人有W3C的API,还可以去MDN上去找,但是我觉得API上说的不全,M...
    顽皮的雪狐七七阅读 4,060评论 0 6
  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 2,053评论 1 10
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,716评论 2 17
  • 前言 原文地址&&我的博客 知乎&&知乎专栏 简书 河南前端交流群官网 上次写了一篇几个让我印象深刻的面试题(一)...
    JayZangwill阅读 1,915评论 0 0