面试官最爱坑人的5道编程题,答不对直接挂
无意间发现了一个巨牛巨牛巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看,传送门https://blog.csdn.net/HHX_01
前言
今天咱们聊点实在的——面试。
都说面试是技术人的"第二战场",代码写得再好,面试时栽在那些"看似简单实则暗藏杀机"的题上,那也是白搭。我在AI这行摸爬滚打这么多年,见过太多技术大牛因为轻敌,被面试官几道"送分题"直接送走。
别慌,今天我就给大家扒一扒2025年面试官最爱挖坑的5道编程题。这些题看着人畜无害,实际个个都能让候选人当场社死。看完这篇文章,下次面试遇到,你就能会心一笑:就这?
第一题:那个让人抓狂的this
来,先看段代码,你猜输出啥?
const obj = {
name: 'AI大神',
sayHi: function() {
setTimeout(function() {
console.log('Hello, ' + this.name);
}, 100);
}
};
obj.sayHi();
很多兄弟一看,这不明摆着输出"Hello, AI大神"吗?obj调用的sayHi,this肯定指向obj啊!
坑在哪? 面试官就等着你这句话呢。
实际上,这段代码输出的是Hello, undefined(严格模式下)或者Hello, (非严格模式)。因为setTimeout里的回调函数是普通函数,在浏览器环境下,它里面的this默认指向window,而window.name是个空字符串或者未定义。
这就好比你去KTV唱歌,明明是你点的歌,结果话筒被隔壁桌的大哥抢过去唱了。setTimeout就是那个"大哥",它把this的指向给抢走了。
怎么破? 用箭头函数啊朋友们:
setTimeout(() => {
console.log('Hello, ' + this.name);
}, 100);
箭头函数没有自己的this,它会"继承"外层的this,就像你跟在大哥后面,话筒最后还是回到你手里。
第二题:Python的"共享饭盒"
来看这道Python题,这也是面试官常玩的套路:
def add_item(item, items=[]):
items.append(item)
return items
print(add_item(1))
print(add_item(2))
print(add_item(3))
你可能想,这不就是往列表里加东西吗?第一次[1],第二次[2],第三次[3],多简单。
坑在哪? Python的默认参数在函数定义时就被计算了,而且只计算一次。也就是说,那个items=[]是在你写代码的时候就创建了,每次调用都是往同一个列表里加东西。
实际输出是:
[1]
[1, 2]
[1, 2, 3]
这就像你带了个饭盒去公司,第一天放了鸡腿,第二天放了青菜,第三天放了米饭。结果你打开饭盒一看,里面啥都有——因为这几天你用的是同一个饭盒!
怎么破? 把默认参数设为None:
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
这样每次调用都会新建一个列表,各自吃各自的,互不干扰。
第三题:闭包里的"定时炸弹"
这道题在JavaScript面试中出现的频率高得吓人:
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 100);
}
很多人信誓旦旦地说:输出0,1,2,3,4嘛,循环五次,每次打印当前的i。
坑在哪? var声明的变量是函数作用域,不是块级作用域。等setTimeout的回调执行时,循环早就跑完了,i已经变成了5。而且由于五个回调共享同一个i,最后打印的全是5。
输出结果是:5,5,5,5,5。
这就像你约了五个朋友明天中午12点吃饭,但你跟他们说的是"明天吃我明天想吃的"。结果到了明天,你只想吃火锅,五个人全被拉去吃火锅了——他们拿到的都是你"最后的状态",而不是约定时的状态。
怎么破? 用let代替var:
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 100);
}
let有块级作用域,每次循环都会创建一个新的i,就像你跟每个朋友单独约定,每个人都记住了当时的"快照"。
或者用闭包把当时的值"锁"住:
for (var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, 100);
})(i);
}
第四题:0.1加0.2为什么不等于0.3
这道题堪称面试界的"脑筋急转弯":
console.log(0.1 + 0.2 === 0.3);
你肯定会说,这不是true吗?小学数学白学了?
坑在哪? 计算机存储小数是用二进制浮点数,而0.1和0.2转换成二进制是无限循环小数,就像1/3在十进制里是0.333...一样。计算机存不下无限位,只能截断,这就产生了精度误差。
实际上0.1 + 0.2等于0.30000000000000004,当然不等于0.3。
这就像你去买东西,标价0.1元和0.2元,你给了0.3元,收银员却说你给少了——因为在他眼里,你给的其实是0.30000000000000004元,他还得找你零(虽然这个零头小得离谱)。
怎么破? 别用===直接比较浮点数,而是看差值是否足够小:
Math.abs(0.1 + 0.2 - 0.3) < 1e-10;
或者先把小数转成整数计算,算完再转回来:
(0.1 * 10 + 0.2 * 10) / 10 === 0.3; // true
第五题:异步世界的"插队游戏"
最后一道题,也是最能看出候选人JS功底的题:
console.log('1');
setTimeout(function() {
console.log('2');
}, 0);
Promise.resolve().then(function() {
console.log('3');
});
console.log('4');
你猜输出顺序是啥?1,2,3,4?还是1,4,2,3?
坑在哪? 这里考察的是事件循环(Event Loop)和任务队列的知识。setTimeout是宏任务(MacroTask),Promise.then是微任务(MicroTask)。
JS执行顺序是:同步代码 → 微任务 → 宏任务。
所以setTimeout虽然延迟是0,但它被扔进了宏任务队列,要等当前同步代码执行完、微任务也执行完,才轮得到它。
输出结果是:1,4,3,2。
这就像你在银行排队,同步代码是VIP客户直接办理;Promise是"快速通道"里的客户,VIP办完后他们先上;setTimeout虽然来得早,但拿的是普通号,只能老老实实等着。
怎么破? 记住这个口诀:同步优先,微任务插队,宏任务靠后。2025年了,Node.js和浏览器的事件循环机制虽然有细微差别,但这个基本原则是不变的。
写在最后
朋友们,看完这5道题,是不是感觉后背发凉?这些题表面上考的是语法细节,实际上考的是你对语言底层机制的理解。就像练武功,招式好看没用,得懂内功心法。
现在各大厂面试越来越卷,2025年甚至开始考AI模型部署和LLM调优了,但基础题依然是个照妖镜。基础不牢,地动山摇。那些花里胡哨的AI框架玩得再溜,要是栽在this指向这种"幼儿园"问题上,面试官只会觉得你是个"调参侠",不是真正的工程师。
下次面试前,把这5道题拿出来温习温习。遇到面试官挖坑,你就淡定地填上,然后看着对方惊讶的表情,心里默念:就这?
对了,如果你还遇到过其他"坑爹"的面试题,欢迎在评论区分享,咱们一起研究研究,看看面试官还能玩出什么花样。毕竟,面试这事儿,知己知彼,才能百战不殆嘛。
下一篇文章,我准备给大家讲讲《AI时代程序员的核心竞争力到底是什么》,感兴趣的朋友记得点个关注,咱们下期见!
无意间发现了一个巨牛巨牛巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看,传送门https://blog.csdn.net/HHX_01
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)