一份头条前端面试准备[整理稿]

JS打乱数组
function shuffle(arr) {
    let i = arr.length;
    while (i) {
        let j = Math.floor(Math.random() * i--);
        [arr[j], arr[i]] = [arr[i], arr[j]];
    }
}
JS ajax
//步骤一:创建异步对象
var ajax = new XMLHttpRequest();
//步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数,动态的传递参数starName到服务端
ajax.open('get','getStar.php?starName='+name);
//步骤三:发送请求
ajax.send();
//步骤四:注册事件 onreadystatechange 状态改变就会调用
ajax.onreadystatechange = function () {
if (ajax.readyState==4 &&ajax.status==200) {
    //步骤五 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
    console.log(ajax.responseText);//输入相应的内容
  }
}
JS bind 实现
if (!Function.prototype.bind) {
    Function.prototype.bind = function () {
        var self = this,                        // 保存原函数
        context = [].shift.call(arguments), // 保存需要绑定的this上下文
        args = [].slice.call(arguments);    // 剩余的参数转为数组
        return function () {                    // 返回一个新函数
            self.apply(context,[].concat.call(args, [].slice.call(arguments)));
        }
    }
}

Function.prototype.bind = function (...arg) {
    var self = this;
        var newArr = [...arg];                       // 保存原函数
    var context = newArr.shift(); // 保存需要绑定的this上下文
    return function (...arg2) {
                var arr = [...newArr];  
                Array.prototype.push.apply(arr,arg2)
                self.apply(context,arr);
    }
}
懒加载
let lazyImages = [...document.querySelectorAll('.lazy-image')]
let inAdvance = 300 // 自定义一个高度,当距离300px到达图片时加载

function lazyLoad() {
    lazyImages.forEach(image => {
        if (image.offsetTop < window.innerHeight + window.pageYOffset + inAdvance) { // 距离xxpx时加载图片
            image.src = image.dataset.src
            image.onload = () => image.classList.add('loaded')
        }
    })

    // if all loaded removeEventListener
}

lazyLoad()

window.addEventListener('scroll', _.throttle(lazyLoad, 16)) // 用到了lodash的节流函数
window.addEventListener('resize', _.throttle(lazyLoad, 16))
JS实现promise
function PromiseM(){
    this.status='pending';
    this.msg='';
    var process=arguments[0];
    var that=this;
    process(function(){
        that.status='resolve';
        that.msg=arguments[0];
    },function(){
        that.status='reject';     
        that.msg=arguments[0];           
    });
    return this;
}
PromiseM.prototype.then=function(){
    if(this.status=='resolve'){
        arguments[0](this.msg);
    }
    if(this.status=='reject'&&arguments[1]){
        arguments[1](this.msg);
    }
}
JS发布订阅模式
const event = {
    clientList: [],
    listen: function(key , fn) {
        if (this.clientListen[key]) {
            this.clientList[key] = []
        }
        this.clientList[key].push(fn)
    },
    trigger: function() {
        const key = Array.prototype.shift.call(arguments)
        const fns = this.clientList[key]
        if (!fns || fns.length === 0 ) {
            return false
        }
        for (let i = 0, fn ;fn = fns[i++];) {
            fn.apply(this, arguments)
        }
    },
    remove : function(key , fn) {
        const fns = this.clientList[key]
        if (!fns) {
            return false
        }
        if (!fn) {
            fns && (fns.length = 0)
        } else {
            for (let l = fns.length - 1; l>=0; l--) {
                const _fn = fns[l]
                if ( _fn ===fn) {
                    fns.splice(l, 1)
                }
            }
        }
}

const installEvent = (obj) => {
    for (let i in event) {
        obj[i] = event[i]
    }
}
JSONP
var script = document.createElement('script');
  script.type = 'text/javascript';

  // 传参并指定回调执行函数为onBack
  script.src = 'http://www.domain-com:8080/login?user=admin&callback=onBack';
  document.head.appendChild(script);

  // 回调执行函数
  function onBack(res) {
      alert(JSON.stringify(res));
  }
JS 获取url参数
function getQueryString(name) { 
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); 
    var r = window.location.search.substr(1).match(reg); 
    if (r != null) return unescape(r[2]); return null; 
}
CSS 无限旋转
@keyframes rotate{
    0%{
        transform: rotate(0);
      }
    50%{
        transform:rotate(200deg);
    }
    100%{
         transform: rotate(0);
        }
    }
 
.rotate{
    transition: 0.5s;
    transform-origin: 30px 30px;  
    animation: rotate 10s linear infinite;  /*开始动画后无限循环,用来控制rotate*/
}
CSS 卡牌翻转
.wutai{
    position: relative;
    perspective: 800px;
    width: 220px;
    height: 292px;
    transform-style: preserve-3d;
}
#trans{
    position: absolute;
    width: 100%;
    height: 100%;
    transition: all 1s;
    transform-style: preserve-3d;
}
        .back{transform: rotateY(180deg);}
        .flip{transform: rotateY(180deg);}

display 有兼容性怎么办
.box{
    display: -webkit-box;  /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
    display: -moz-box;     /* 老版本语法: Firefox (buggy) */
    display: -ms-flexbox;  /* 混合版本语法: IE 10 */
    display: -webkit-flex; /* 新版本语法: Chrome 21+ */
    display: flex;         /* 新版本语法: Opera 12.1, Firefox 22+ */
}

.flex1 {  
    -webkit-box-flex: 1   /* OLD - iOS 6-, Safari 3.1-6 */  
    -moz-box-flex: 1;     /* OLD - Firefox 19- */              
    -webkit-flex: 1;      /* Chrome */  
    -ms-flex: 1           /* IE 10 */  
    flex: 1;              /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
算法 选择排序
function selectionSort(arr) {
    var len = arr.length;
    var minIndex, temp;
    for (var i = 0; i < len - 1; i++) {
        minIndex = i;
        for (var j = i + 1; j < len; j++) {
            if (arr[j] < arr[minIndex]) {     //寻找最小的数
                minIndex = j;                 //将最小数的索引保存
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
    return arr;
}
二分查找算法
function binarySearch(data,item,start,end){
    var end=end || data.length-1;
    var start=start || 0;
    var m=Math.floor((start+end)/2);
    if(item === data[m]){
        return m;
    }else if(item<data[m]){
        return binarySearch(data,item,start,m-1) //递归调用
    }else{
        return binarySearch(data,item,m+1,end);
    }
    return false;
}
归并算法
function merge(left, right) {
  var tmp = [];

  while (left.length && right.length) {
    if (left[0] < right[0])
      tmp.push(left.shift());
    else
      tmp.push(right.shift());
  }

  return tmp.concat(left, right);
}

function mergeSort(a) {
  if (a.length === 1) 
    return a;

  var mid = ~~(a.length / 2)
    , left = a.slice(0, mid)
    , right = a.slice(mid);

  return merge(mergeSort(left), mergeSort(right));
}
快速排序
const quickSort = (arr) => {
    let left = 0;
    let right = arr.length - 1;
    whlie(left < right) {
        while(arr[right] >= arr[0] && left < right){
            right -= 1
        }
        while(arr[left] <= arr[0] && left < right) {
            left++;
        }
        if (right === left) {
      let mid=arr[right];
      arr[right]=arr[0];
      arr[0]=mid;
      break;
    }
        // 当左指针小于右指针的位置,交换两个指针当前位置的元素
    let tem=arr[right];
    arr[right]=arr[left];
    arr[left]=tem;
    }
    return quickSort(arr.slice(0,left)).concat(arr.slice(left,right+1)).concat(quickSort(arr.slice(right+1)));
}


function _quickSort(num, left, right) {
    if (left >= right) return; // 若左右指针相遇,待排序数组长度小宇1,即递归的终点,return(注意不能写成left==right,这里left是有可能大于right的)。
    var i = left, j = right, flag = left; // 定义可移动的左右指针 i,j,定义flag为基数下标。
    while (i < j) { // 在i<j时不断循环,i一旦与j碰头,则跳出循环。
        while (num[j] >= num[flag] && j > flag) j--; // j不断左移,找到在num[flag]右侧且比它大的数。
        if (i >= j) {
            break; // 由于j可能已被改变,需再次判断i与j是否碰头。
        }
        while (num[i] <= num[flag] && i < j) i++; // i不断右移,找到且比基数小的数,且i不能与j碰头。(由于两次交换已合并,此处不需要使得i在flag左侧)
        // num[flag] num[j] num[i]三者换位,可用ES6语法糖[num[flag],num[j],num[i]] = [num[j],num[i],num[flag]];
        let temp = num[flag]; 
        num[flag] = num[j];
        num[j] = num[i];
        num[i] = temp
        flag = i; // 基数已经在原num[i]的位置,flag同时也要赋值成i。
    }
    _quickSort(num, left, flag - 1); // 将flag左边数组作为待排序数组,递归调用。
    _quickSort(num, flag + 1, right); // 将flag右边数组作为待排序数组,递归调用。
}
节流函数
function throttle(method,delay,duration){
    var timer=null;
    var begin=new Date();    
    return function(){                
        var context=this, args=arguments;
        var current=new Date();        
        clearTimeout(timer);
        if(current-begin>=duration){
            method.apply(context,args);
            begin=current;
        }else{
            timer=setTimeout(function(){
                method.apply(context,args);
            },delay);
        }
    }
}

// 函数消抖
function debounce(method,context){
    clearTimeout(method.tId);
    method.tId=setTimeout(function(){
        method.call(context)
    },300)
}
function debounce(method,delay){
    var timer = null; 
    return function(){
        var context = this,args = arguments;
        clearTimeout(timer); 
        timer = setTimeout(function(){
            method.apply(context,args); 
        },delay);
    }
}

const throttle = (method, delay, duration) => {
    const date = new Date();
    let timer = null;
    return function (...arg){
        const current = new Date();
        clearTimeOut(timer);
        if(current - data >= duration){
            method.apply(this, arg);
            date = current;
        }
        timer = setTimeOut(() => {
            method.apply(this, arg);
        }, delay)
    }
}
IndexOf的实现
function ArrayIndexOf(arr,value,n){
    var i=isNaN(n)?0:n;//有第三参时
        i=(i<0)?arr.length+i:i;//第三参为负数时
    for(i;i<arr.length;i++){
        if(arr[i]===value){return i;}                   
    }return -1;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341