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


    相关知识点

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

    题目&答案

    • 函数记忆,判断是不是质数.
      方法一:
      function isPrime1(n){
          if(n<=3){return true}
          else{
            for(var i=2;i<Math.sqrt(n);i++){
              if(n%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(/[a-z]+/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);
            }
           }
        }
  • 相关阅读:
    JavaScript 为字符串添加样式 【每日一段代码80】
    JavaScript replace()方法 【每日一段代码83】
    JavaScript for in 遍历数组 【每日一段代码89】
    JavaScript 创建用于对象的模板【每日一段代码78】
    html5 css3 新元素简单页面布局
    JavaScript Array() 数组 【每日一段代码88】
    JavaScript toUTCString() 方法 【每日一段代码86】
    位运算
    POJ 3259 Wormholes
    POJ 3169 Layout
  • 原文地址:https://www.cnblogs.com/sybboy/p/6525988.html
Copyright © 2020-2023  润新知