Sunshine168 / resume

My resume
3 stars 1 forks source link

# 前端面试准备(day1) #1

Open Sunshine168 opened 7 years ago

Sunshine168 commented 7 years ago

js算法与应用

排序部分

快速排序

    // 从小到大的快速排序
        function sort(array){
            //slice用于截取数组,通过slice,从0到arr.length 复制出一个新的数组
            var temp_array = array.slice(0)
             quickSort = function(arr){
                  //数组已经为空了
                   if(arr.length<=1){
                    return arr;
                   }
                   //数组可以继续分割
                   //获取中间元素坐标,并取出该元素
                   var provIndex = Math.floor(arr.length/2),
                       prov   = arr.splice(provIndex,1)[0],
                            left = [],
                            right = [];

                            for(var i = 0 ; i<arr.length ; i++){
                                  if(arr[i]>prov){
                                      //大于中间元素向右
                                      right.push(arr[i])
                                  }else{
                                    left.push(arr[i])
                                  }
                            }

                           return quickSort(left).concat([prov],quickSort(right))
            }
            return quickSort(temp_array);
        }

优化过的冒泡排序

//优化后的冒泡排序
    function baboSort(arr){
        //复制数组
        var temp_arr  = arr.slice(0),tag,temp;
        for(var i = 0 ;i<temp_arr.length ;i++){
              tag = 0;
              for(var j =temp_arr.length-1 ;j>i ;j--){
                   if(temp_arr[j]>temp_arr[j+1]){
                       temp = temp_arr[j];
                       temp_arr[j] = temp_arr[j+1];
                       temp_arr[j+1] = temp ; 
                       tag = 1;
                   }
              }
              if(tag === 0 ){break}
        }
        return temp_arr;
    }

数组去重

   //消除数组重复
   var array = [4,2,5,2,8,4,9,1,1]
   //方法一、现代浏览器方法(IE9,chrome,edge,firefox..)
    var newArray = array.filter(function(ele, pos,self){
        return pos === self.indexOf(ele)
    })

   //方法二、
function unique(arr) {
    var ret = [];
    var len = arr.length;
    var tmp = {};
    var tmpKey;
    for(var i=0; i<len; i++){
        //序列成一个键进行去重
        tmpKey = typeof arr[i] + JSON.stringify(arr[i]);
        if(!tmp[tmpKey]){
            tmp[tmpKey] = 1;
            ret.push(arr[i]);
        }
    }
    return ret;
} 
  console.log(unique(array))
  //方法三、(es6 IE 11 CHROME 38)
  function unique(arr){
    //set元素都是唯一的
    var set =new Set(arr);
     return Array.from(set)
  }

编写一个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;
          }

实现对象的clone

// 方法一:
Object.prototype.clone = function(){
        //根据构造函数判断是数组还是对象,分别初始化
        var o = this.constructor === Array ? [] : {};
        for(var e in this){
               //是对象就递归调用clone 是数组就根据(e)index 赋值
                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;
        }
    }

小题合集

生成[x,y]范围的随机整数

function Random(min,max){
    return Math.random()*(max-min)+min+1
}
//random产生[0,1) 如果要达到1的便捷需要+1

小数精度问题 0.2+0.1?

console.log(0.2 + 0.1);//0.30000000000000004 精度丢失
//解决办法
 function add(num1, num2){
  let r1, r2, m;
  //转换为字符串来获取小数位数
  r1 = (''+num1).split('.')[1].length;
  r2 = (''+num2).split('.')[1].length;
  //取位数最长的
  m = Math.pow(10,Math.max(r1,r2));
  return (num1 * m + num2 * m) / m;
}
console.log(add(0.2+0.1)) //0.3

已知数组var stringArray = [“This”, “is”, “Baidu”, “Campus”],Alert出”This is Baidu Campus”

var stringArray = ['This', 'is', 'Baidu', 'Campus']
console.log(stringArray.join(" "))

已知有字符串foo=”get-element-by-id”,写一个function将其转化成驼峰表示法”getElementById”

function hump(str){
     var newStr = "", flag  = false;
     for(var i = 0 ; i<str.length; i++){
          if(str[i]==='-'){
             flag = true;
          }else{
            if(flag){
                newStr += str[i].toUpperCase(); 
                flag = false;
            }else{
                newStr += str[i]; 
            }

          }
     }
     return newStr;
}

var numberArray = [3,6,2,4,1,5]; 实现倒排,排序。

//顺排,倒排
var numberArray = [3,6,2,4,1,5]; 
//sort实现
var sortArr = numberArray.sort(function(a,b){
    return a - b;
})
//倒排
var sortArr = numberArray.sort(function(a,b){
    return b - a;
})

怎样添加、移除、移动、复制、创建和查找节点


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

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

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

//添加、移除、替换、插入

      appendChild()

      removeChild()

      replaceChild()

      insertBefore()
//查找

   getElementsByTagName()    //通过标签名称

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

      getElementById()    //通过元素Id,唯一性
      querySelector()    // 查找单个元素
      querySelectorAll()  //查找所有元素

将一个#fffff类型的数据转换为rgb(255,255,255)形式

遍历ul中li的内容

  (function(){
               var liList = document.getElementsByTagName("li");
                   for(var i = 0 ; i<liList.length ;i++){
                    console.log(liList[i].innerHTML);
                   }
             })()

查找一个对象是否具有某个属性

            function getNodeById(data,id){
                 if(data['id']==id){
                    return data;
                 }else{
                     if(data.hasOwnProperty("children")){
                          var node = null ;
                          data["children"].every(function(element){
                                 node = getNodeById(element,id); 
                                 if(node){ 
                                    return ;
                                 }else{
                                    return true;
                                 }
                          }) 
                         return node;
                     }else{
                        //找不到节点
                        return ;
                     }
                 }
            }

请写出以下执行结果

var myObject = {
    foo: "bar",
    func: function() {
        //指向对象myObject
        var self = this;
        console.log("outer func:  this.foo = " + this.foo);
        console.log("outer func:  self.foo = " + self.foo);
        (function() {
          //this指向windows 严格模式指向undefined
            console.log("inner func:  this.foo = " + this.foo);
            //指向对象
            console.log("inner func:  self.foo = " + self.foo);
        }());
    }
};
myObject.func();

请写出以下执行结果

function foo1()
{
  return {
      bar: "hello"
  };
}

function foo2()
{
  return
  {
      bar: "hello"
  };
}
console.log(foo1())//{bar:"hello"}
console.log(foo2())//undefined
//why?,等价于
function foo3()
{
  return;
  {
      bar: "hello"
  };
}
console.log(foo3())

关于NaN ,NaN是一个数字吗? 判断NaN

console.log(typeof NaN);//number
console.log(Number.isNaN(NaN))//true
console.log(NaN === NaN);//false
console.log(NaN == NaN);// fals

变量问题

//2、变量问题
(function(){
  var a = b = 3;
  //a是局部变量,b是全局变量
  //等价于 var a = b ,b = 3 ;
})();

console.log("a defined? " + (typeof a !== 'undefined'));   
console.log("b defined? " + (typeof b !== 'undefined'));

var a = {
  n:1
},
b = a ;
a.x = a = {n:2}
/*
(先寻找变量再赋值)第一阶段初始化的时候值已经保存下来了 a.x是a的引用指向x,此时x未声明所以此时指向null,a已经声明了,a指向堆中的常量{n:1},
第二阶段赋值, a指向堆中的常量{n:2},a.x指向a即指向常量{n:2}
需要注意的是此时a.x在第一阶段保存的引用是一开始a的变量位置,跟赋值过来的a已经不是一个变量了
*/
console.log(b)//{n:1}
console.log(a)//{n:2}
console.log(a.x)//undefined

  var a = 2, b=1;
    function temp(a){
       //a有声明所以作为局部变量处理
       a = 4 ;
       console.log(a)//4
       //b无声明所以当做全局变量
       b = 4 
       console.log(b)//4
       //全局变量处理
       c = 5 
       console.log(c)//5
    }
   // temp()
   // temp(4)
   //如果将所在函数注释后会如何?ReferenceError: c is not defined
   console.log(a)//2
   console.log(b)//4
   console.log(c)//5

写一个按照下面方式调用都能正常工作的 sum 方法

console.log(sum(2,3));   // Outputs 5
console.log(sum(2)(3));  // Outputs 5
function sum(){
    var sum =0;
  if(arguments.length<=1){
     sum = arguments[0];
    //只有一个情况下需要储存当前参数用作下次累加
    return function(value){
      sum += value
      return sum;
    }
  }else{
       return [].reduce.call(arguments,function(sum,value){
        return sum+value;
       },0)
  }
}
//由此引出
 /*
由此延伸call apply call,apply的不同点
call(context,arguments...) //arguments... 是若干个参数
apply(context,arguments) //arguments 是 数组
call的调用速度比apply快
相同点 改变函数执行的环境
第一次参数为null的时候指向windows
 模拟实现call,apply?
 见https://github.com/mqyqingfeng/Blog 获益良多
 最关键的是
模拟的步骤可以分为:
将函数设为对象的属性
执行该函数
删除该函数
 */

IIFE (Immediately-Invoked Function Expression)

for(var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);  
    }, 1000);
}
//输出的是5个5
//解决方式
for(var i = 0; i < 5; i++) {
    (function(i){
        setTimeout(function() {
        console.log(i);  
    }, 1000);
    })(i)
}
//1 2 3 4 5
//那这个呢?
for(var i = 0; i < 5; i++) {
    (function(){
        setTimeout(function() {
        console.log(i);  
    }, 1000);
    })(i)
}
//i此时使用的还是外部的i 因为这样就是提供参数,但是函数本身没有形参
//es6解决办法?
for(let i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);  
    }, 1000);
}
//可以延伸到什么部分?
console.log(5)
for(let i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);  
    }, 1000);
}
console.log(5)
//执行顺序 5->5->1~4
//原因?eventLoop,再看一个

var start = new Date();
setTimeout(function(){
  console.log(4)
  var time = start - new Date();
  console.log(`time is `)
},2)
setTimeout(function(){
  console.log(4)
  var time = start - new Date();
  console.log(`time2 is `)
},0)

//time 是多少?  还有这个又是多少?
//基于 chrome 版本 59.0.3071.115(正式版本) (64 位)
/* 像定时器、计时器  Promise 这类的异步操作   是放在任务队列中的,只有js主进程栈中的任务执行完才会执行。详情见 http://www.ruanyifeng.com/blog/2014/10/event-loop.html
(基于0秒的setTimeout立即执行已过期)
*/
/*在nodejs中进行实验
hello
4
time2 is
4
time is
结果相同
但是在nodejs中 eventloop的运行机制与浏览器不一样(暂未深入了解,详情见阮老师的文章)
*/

IIFE还有用处? 防止变量污染

类型问题

简便的类型转换

var num1 ="1a9c",num2 = 19,num3 ="20"
console.log(parseInt(num1)+num2) //20
num1 = "a1"  
console.log(parseInt(num1)+num2) //NaN
console.log(num3-0)  //20

真假值

极假(falsy) false null undefined ' ' 0 NaN 其他都是真值