Skip to content

去哪儿秋招AI笔面试

  1. typeof/instanceof/Object.prototype.toString 区别

    📌 回答

    • typeof 运算符返回一个字符串,表示操作数的类型,返回的结果包括:number、string、boolean、undefined、object、function、symbol、bigint。
    • typeof 有一定局限性,比如 typeof null 是 object,typeof 不能区分数组、普通对象、Date、RegExp 等。
    • instanceof 运算符用于检测某个对象是否出现在对应构造函数的原型链上。
    • instanceof 受限于全局环境,不同的全局环境下构造函数的原型链是不同的。比如,Iframe 的环境中,instanceof 无法判断对象是否是 Array 的实例。
    • Object.prototype.toString 方法返回一个表示该对象的字符串。
    • 可以通过 call、apply 方法改变 this 指向,从而实现对任意对象的类型判断。并且,不会受到全局环境的影响。同时,返回的结果也可以精确判断,比如 Object.prototype.toString.call([]) 返回 [object Array],Object.prototype.toString.call(new Date()) 返回 [object Date]。
  2. 实现 Vue 模版引擎的基本指令

    🔍 展开代码
    1.html
    html
    <!DOCTYPE html>
    <html>
    
    <head>
        <style>
            div {
                margin: 20px 0;
            }
        </style>
    </head>
    
    <body>
        <!-- Block 1 -->
        <div v-if="1 + 1 === 2" class="div1">
            “去哪儿 ”认识到在线旅游市场的用户需求已经逐渐变化...
        </div>
        <div v-else-if="1 + 1 === 2" class="div-else-if-after-true-if">
            这个 v-else-if 紧跟在一个 true 的 v-if 后面,所以它不应该显示。
        </div>
    
        <!-- Block 2 -->
        <div v-if="1 + 1 !== 2" class="div2">
            2012年12月,去哪儿顺利通过PCI认证...
        </div>
        <div v-else-if="1 + 2 === 3" class="div3">
            2021年8月,中国信息通信研究院发起的“卓信大数据计划”...
        </div>
        <div v-else-if="false" class="div4">
            2022年1月,去哪儿旅行App获得移动互联网应用程序(App)安全认证证书...
        </div>
    
        <!-- v-show elements -->
        <div v-show="true" class="div5">
            2023年8月21日,去哪儿平台数据出境申报获得国家网信办批准...
        </div>
        <div v-show="false" class="div6">
            “去哪儿”为旅游者提供国内外机票、酒店、会场、度假和签证服务的深度搜索...
        </div>
    
        <!-- Non-directive element -->
        <span class="span1">
            “去哪儿”是通往中国旅游市场,以及接触广大在线旅游消费者的通行证...
        </span>
    
        <script>
            const rootElement = document.querySelector('body');
            const children = Array.from(rootElement.children);
    
            // 预处理:收集每个元素的 DOM 节点和指令信息(静态结构,不依赖实时DOM)
            const elementInfos = children.map(element => ({
                element: element,
                directive: findDirective(element) // 待实现:识别元素的指令(v-if/v-else-if/v-show)
            }));
    
    
            let ifBlockMet = false; // 跟踪v-if链是否已有条件满足
    
            // 遍历静态结构,处理每个元素的指令逻辑
            for (let i = 0; i < elementInfos.length; i++) {
                const { element, directive } = elementInfos[i];
    
                if (!directive) {
                    ifBlockMet = false;
                    continue;
                }
    
                // 获取指令表达式并求值
                const directiveValue = element.getAttribute(directive);
                const result = expressionFun(directiveValue)();
    
                // v-if逻辑
                if (directive === 'v-if') {
                    if (result) { 
                        ifBlockMet = true; 
                    } else { 
                        ifBlockMet = false; 
                        element.parentNode.removeChild(element); 
                    } 
                }
    
                // v-else-if逻辑
                else if (directive === 'v-else-if') {
                    const prevInfo = elementInfos[i - 1];
                    const prevDirective = prevInfo ? prevInfo.directive : null;
    
                    // 合法性校验:前序必须是v-if/v-else-if,且当前链未满足
                    if (!/v-if|v-else-if/.test(prevDirective) || ifBlockMet) {
                        element.parentNode.removeChild(element);
                        continue;
                    }
    
                    if (result) {
                        ifBlockMet = true;
                    } else {
                        ifBlockMet = false;
                        element.parentNode.removeChild(element);
                    }
                }
    
                // v-show逻辑
                else if (directive === 'v-show') {
                    if (!result) { 
                        element.style['display'] = 'none'; 
                    } 
                }
            }
    
            /**
             * 判断元素是否包含v-if/v-else-if/v-show指令
             */
            function findDirective(element) {
                const dis = ['v-if', 'v-else-if', 'v-show']; 
                for (const d of dis) { 
                    if (element.hasAttribute(d)) { 
                        return d; 
                    } 
                } 
                return undefined; 
            }
    
            /**
             * 将表达式字符串转为可执行函数
             */
            function expressionFun(attrValue) {
                return function () { 
                    return eval(attrValue); 
                }; 
            }
        </script>
    </body>
    
    </html>
  3. OSI 七层模型以及每一层的作用?

    📌 回答

    • 物理层:负责比特流的传输,包括电气特性、光学特性、物理介质和物理连接等。这一层,涉及到的概念有:网线、光纤、网卡、双绞线、集线器等。
    • 数据链路层:在相邻节点传输帧,提供差错的检测、纠正以及 MAC 寻址等。这一层涉及到的概念有:以太网协议、ARP、交换机等。
    • 网络层:端到端的寻址和路由的选择,负责把数据报文送达到目标主机。这一层会涉及到 IP 协议、路由表、子网掩码等。
    • 传输层:能够借助 TCP/UDP 协议,实现端到端传输,并提供端口管理等功能。
    • 会话层:负责建立、维护和终止会话。这里涉及到 RPC、SQL Session 等技术。
    • 表示层:负责数据的加密、压缩和解压缩,确保数据能够被正确地表示,进一步保证应用层能正确处理数据。比如 TLS/SSL 就是在这一层实现的。
    • 应用层:负责应用程序的通信。涉及到的协议有很多,比如 HTTP、HTTPS、FTP、SMTP、POP3、DNS 等。
  4. 如何实现可靠传输?

    📌 回答

    • 数据分段与编号:每个报文段都带有自己的一个序号,服务端可以按照序号进行数据排序和重组,避免数据的乱序问题。
    • 确认应答机制(ACK):接收方收到数据后,会发送一个确认应答报文给发送方,确认数据已经被正确接收。如果出现 ACK 丢失现象,发送方会对数据进行重传。
    • 超时重传机制(RTO):基于 RTT 动态平滑计算,在一定时间内如果有数据没有收到确认应答,则认为数据发送失败,进行重传。
    • 滑动窗口机制:发送方可以同时发送多个报文,而不必等待接收方确认应答。接收方可以根据接收窗口的大小,来控制接收方可以接收的数据量。
    • 流量控制:发送方可以根据接收方的窗口大小 RWND 来控制发送数据的速率,避免发送方发送的数据过快,导致接收方处理不过来。
    • 拥塞控制:发送方根据网络的拥塞情况,调整发送数据的速率,避免网络拥塞。
  5. 拥塞控制算法以及彼此之间的配合关系?

    📌 提示

    • 慢启动:初始化阶段拥塞窗口大小为 1,每收到一个 ACK,拥塞窗口大小指数增长。这个机制,用于快速探测网络容量。
    • 拥塞避免:当拥塞窗口大小超过阈值时,进入拥塞避免阶段。拥塞窗口大小线性增长,避免网络拥塞。
    • 快速重传:当发送方收到 3 个重复 ACK 时,立即触发快速重传机制,重传丢失段。
    • 快速恢复:当发送方检测到丢包以后,阈值和窗口大小减半但不会到 1,避免了吞吐量的剧烈下降。然后,拥塞窗口大小线性增长,直到达到阈值。
    • 总结:指数增长探测带宽,到阈值之后线性增长并进入稳定阶段;检测到丢包会进入快速恢复,不必等待超时。整体遵循 AIMD 算法——正常时加性增,丢包时乘性减。
  6. 给定一个数组,你可以对其中一个数字加一。要求新数组能够满足以下公式结果最大化:

    S=i=1n1j=i+1n(aiaj)2