前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >近期校招笔试题

近期校招笔试题

作者头像
多云转晴
发布2020-11-03 14:31:45
6580
发布2020-11-03 14:31:45
举报
文章被收录于专栏:webTower

二分查找数组中出现的第一个元素

代码如下:

代码语言:javascript
复制
function binarySearch(array, target) {
    function getFirstItem(idx) {
        while(idx >= 0 && array[idx] === target) {
            idx -= 1;
        }
        return idx + 1;
    }
    function search(left, right) {
        while(left <= right) {
            let mid = Math.floor((left + right) / 2);
            if(array[mid] === target) {
                // 看看 mid 的左边元素是不是与 target 相等(因此要找第一个出现的元素)
                return getFirstItem(mid - 1);
            } else if(array[mid] > target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }
    return search(0, array.length - 1);
}

防抖、节流

防抖:

代码语言:javascript
复制
function debounce(fn, delay) {
    let timer = null;

    return function(...args) {
        let self = this;
        clearTimeout(timer);
        timer = setTimeout(function() {
            fn.apply(self, args);
        }, delay);
    }
}

节流:

代码语言:javascript
复制
function throttle(fn, delay) {
    let timer = null;
    return function(...args) {
        let self = this;
        // 首次调用不延迟
        if(!timer) {
            fn.apply(self, args);
        }
        if(timer)   return;
        timer = setTimeout(function() {
            fn.apply(self, args);
            timer = null;
        }, delay);
    }
}
防抖和节流的不同

防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。

判断一个链表是否有环

使用快慢指针:

代码语言:javascript
复制
function hasCycle(node) {
    if(!node || !node.next) {
        return false;
    }

    let slow = node;
    let fast = node.next;

    while(slow !== fast) {
        // 如果没有环,则快指针会抵达终点
        if(!fast || !fast.next) {
            return false;
        }
        slow = slow.next;
        fast = fast.next.next;
    }
    // 如果有环,那么快指针会追上慢指针
    return true;
}

使用 Map 或者 Set:

代码语言:javascript
复制
function hasCycle(node) {
    let cache = new Map(),
        temp = node;

    while(temp) {
        cache.set(temp, true);
        temp = temp.next;
        if(cache.get(temp)) {
            return true;
        }
    }
    return false;
}

HTML 模板解析

题目如下:

代码语言:javascript
复制
<script id="test" type="text/html">
    <h1>{{title}} world!</h1>
    <div>
        <h3>My name is {{data.name}}</h3>
        <h4>I'm {{data.age}}</h4>
    </div>
</script>

<script>

    const user = {
        title: 'hello',
        data: {
            name: 'XiaoMing',
            age: 20
        }
    };
    // template 会把数据填充到模板里
    const html = template('test', user);

</script>

可以使用正则表达式来实现:

代码语言:javascript
复制
function template(id, data) {
    let content = document.getElementById(id).innerHTML;
    // 匹配 {{...}}
    const templateReg = /\{\{\s*(.+)\s*\}\}/g;
    // 匹配 a.b[1] 形式的数组
    const arrayReg = /(\w+)\s*\[(\d+)\]/g;
    // 主项就行匹配
    let templateData = templateReg.exec(content);
    while(templateData) {
        // 拿到整体的模板 {{...}} 和 其中的属性
        let [templateStr, protoStr] = templateData;
        // 分离属性链
        let protoArr = protoStr.split('.');
        let tempData = data;

        // 遍历
        protoArr.forEach(proto => {
            // 看看有没有数组
            let execArr = arrayReg.exec(proto);
            if(execArr) {
                let [, protoName, index] = execArr;
                tempData = tempData[protoName][index];
            } else {
                tempData = tempData[proto];
            }
        });
        content = content.replace(templateStr, tempData);
        templateData = templateReg.exec(content);
    }
    return content;
}

两秒后获取数组中的下一个元素

代码如下:

代码语言:javascript
复制
function run(array, callback) {
    let len = array.length, idx = 0;
    function play() {
        if(idx < len) {
            callback(array[idx], idx);
            idx += 1;
            setTimeout(play, 2000);
        }
    }
    setTimeout(play, 2000);
}

const ary = [
    'hello',
    'world',
    '你好呀~',
    'My name is Ming'
];

run(ary, function(item) {
    console.log(item);
});

DOM Diff

Tree Diff

  • 将新旧两棵树逐层对比,找出哪些节点需要更新;
  • 如果节点是组件就进行 Component Diff;
  • 如果节点是标签就进行 Element Diff;

Component Diff

  • 如果节点是组件,就先看组件类型;
  • 类型不同直接替换(删除旧的);
  • 类型相同则只更新属性;
  • 然后深入组件做 Tree Diff(递归);

Element Diff

  • 如果节点是原生标签,则看标签名;
  • 标签名不同直接替换,相同只更新属性;
  • 然后进入标签后代做 Tree Diff(递归)

作用域和作用域链

运行期上下文:当函数执行时,会创建一个称为执行上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行期上下文,当函数执行完毕,它所产生的执行上下文被销毁。

执行上下文包含三个部分:

  • 变量对象(VO,存储着变量和函数声明);
  • 作用域链;
  • this 指向

作用域:上下文中声明的变量和函数的作用范围。分为块级作用域和函数作用域。

每个 JavaScript 函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供 JavaScript 引擎存取,[[scope]] 就是其中之一。

[[scope]] 指的是我们所说的作用域,其中存储了执行期上下文的集合。

作用域链[[scope]] 中存储的执行期上下文对象的集合,这个集合呈链式调用,我们把这种链式链接叫做作用域链。

代码执行过程

  • 创建全局上下文;
  • 全局执行上下文逐行自上而下执行,遇到函数时,函数执行上下文被 push 到执行栈顶层;
  • 函数执行上下文被激活,开始执行函数中的代码,全局执行上下文被挂起;
  • 函数执行完毕,函数执行上下文 pop 移除出执行栈,控制权交还给全局上下文,继续执行下面的代码。

ES5 和 ES6 中的继承

ES5 版:

代码语言:javascript
复制
function Super(age, gender) {
    this.age = age;
    this.gender = gender;
}
Super.prototype.sayAge = function() {
    return this.age;
}

function Sub(name, age, gender) {
    this.name = name;
    Super.call(this, age, gender);
}
Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;
Sub.prototype.sayName = function() {
    return this.name;
}

let sub = new Sub('ming', 18, 'male');
console.log(sub.sayName());
console.log(sub.sayAge());

ES6 版:

代码语言:javascript
复制
class Super{
    constructor(age, gender) {
        this.age = age;
        this.gender = gender;
    }
    sayAge() {
        return this.age;
    }
}
class Sub extends Super{
    constructor(name, age, gender) {
        this.name = name;
        super(age, gender);
    }
    sayName() {
        return this.name;
    }
}

Promise 版 Ajax

代码语言:javascript
复制
function ajax(url, options) {
    options = Object.assign({
        method: 'GET',
        headers: {},
        data: null
    }, options);

    return new Promise((resolve, reject) => {
        let { method, data, headers } = options;
        let xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        for(let header in headers) {
            xhr.setRequestHeader(header, headers[header]);
        }
        // readyState 的值发生变化时,触发这个事件
        xhr.onreadystatechange = function() {
            if(xhr.readyState === 4) {
                if(xhr.status === 200 || xhr.status === 304) {
                    resolve(xhr.response);
                } else {
                    reject(xhr);
                }
            }
        }
        xhr.onerror = function(e) {
            reject(e);
        }
        xhr.send(data);
    });
}

全排列

输入一个没有重复数字的序列,返回其所有可能的全排列。

代码语言:javascript
复制
function permute(nums) {
    function fn(list, tempList, nums) {
        if(tempList.length === nums.length) return list.push([...tempList]);
        for(let i = 0;i < nums.length;i ++) {
            if(tempList.includes(nums[i]))  continue;

            tempList.push(nums[i]);
            fn(list, tempList, nums);
            tempList.pop();
        }
    }

    let result = [];
    fn(result, [], nums);
    return result;
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WebTower 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 二分查找数组中出现的第一个元素
  • 防抖、节流
    • 防抖:
      • 节流:
        • 防抖和节流的不同
    • 判断一个链表是否有环
    • HTML 模板解析
    • 两秒后获取数组中的下一个元素
    • DOM Diff
      • Tree Diff
        • Component Diff
          • Element Diff
          • 作用域和作用域链
            • 代码执行过程
            • ES5 和 ES6 中的继承
              • ES5 版:
                • ES6 版:
                • Promise 版 Ajax
                • 全排列
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档