好吧,我认可太标题党了,这篇文章是经过一道前端面试题引出的纯技术讨论。我先要矫情无比的从中外诗歌提及。javascript
传统的佛学经典里,被世人熟知的有这样一句话:“一花一世界,一叶一菩提,一木一浮生,一草一天堂,一砂一极乐,一方一净土,一笑一尘缘,一念一清静。”前端
昔时佛祖拈花,唯迦叶微笑,既而步往极乐。从一朵花中便能悟出整个世界,得升天堂,佛祖就是佛祖,谁人能有这样的境界。java
同时,早在18世纪,英国伟大的浪漫主义诗人Black名为《天真的暗示》的诗中,也相似写道:"To see a world in a grain of sand, and a heaven in a wild flower",一颗沙里一个世界,一朵野花一座天堂。git
转念,虽卑为码农,咱们写出的代码,却彰显了功力:菜鸟和大神之间的差距,每每工程线上卑微的几行代码,便有天壤之差。github
一道系列面试题,在JS知识体系中虽沧海一粟,但考察点充分评判面试者的能力。
管中窥豹,期待读者有不一样想法与我讨论。面试
题目是我在《effective javascript》一书中提取的。这一星期陆陆续续面试了很多于10我的,其中不乏工做履历突出的候选者。
可是很遗憾没有能彻底在较短期内有较高质量的回答。数组
这道题能够分为先后两个部分,第一部分很简单,通常有必定JS OOP基础的候选者应该均可以答好:微信
一个社交网络有一组成员(member),每一个成员有一个本身的名字,和存储其朋友信息的列表。请实现这样一个Member构造器。网络
正确答案不难理解:frontend
function Member (name) {
this.name = name;
this.friends = [];
}复制代码
是否是很是简单。它的典型错误包括可是不限于:
function Member (name) {
this.name = name;
}
Member.prototype.friends = [];复制代码
关于方法和属性是应该放在原型上,仍是构造函数中,若是您不明白的话,是时候补一补原型原型链的知识了。推荐给你们看一下个人同事颜海镜早在3年前的一篇文章。
一样,这道题上我会顺便考察一下面试者对JS中变量的存储方式,包括堆栈存储的不一样状况和引用赋值的掌握状况。
以上是对JS基础的考察,可是在这道题目的基础上,我进行了更深一步提问。但愿对候选者的临场思惟、JS基础甚至一些设计能力,又更进一步认识。
我要实现一个带环社交网络(社交圈):
var a = new Member('Alice');
var b = new Member('Bob');
var c = new Member('Carol');
var d = new Member('Dieter');
var e = new Member('Eli');
var f = new Member('Fatima');
a.friends.push(b);
b.friends.push(c);
c.friends.push(e);
d.friends.push(b);
e.friends.push(d, f);复制代码
这种状况下,须要实现一个inNetwork方法,判断某目标成员是否在另外一个对象成员的社交圈中。规定:顺着社交链能找到目标成员,就认为在社交圈中。不然,不在其社交圈。
若是刚接触到这样的题目,尤为是在面试现场,做为面试者极可能会慌乱一下。这时候,须要作的就是先准确分析题目。
根据题目,画出符合上述题目代码的实例化网络:
接下来思考,搜索意味着须要遍历整个社交网络。咱们应该:
1)以单个根节点开始,
2)而后添加发现的节点,
3)移除访问过的节点,防止死环
最终实现:
Member.prototype.inNetwork = function (target) {
var visited = {};
var worklist = [this]; // 用于存放社交链上的个体信息,初始时以“本身”做为根节点
while (worklist.length > 0) {
// 将worklist里的最后一项成员删除并取出
var member = worklist.pop();
// 若是存在环的状况,须要避免重复访问
if (member.name in visited) {
continue;
}
visited[member.name] = member;
if (member === target) {
return true;
}
// 将当前成员的朋友列表加入worklist当中,他们都在根节点的社交链上
member.friends.forEach(function(friend) {
worklist.push(friend);
})
}
return false;
}复制代码
我在代码中加上了注释,若是您还不明白也没有关系。建议去跑一下程序,进行debugger和console,尝试去理解。
测试:
a.inNetwork(f) // true
f.inNetwork(a) //false复制代码
哈哈,果真Alice能经过朋友圈查找到Fatima,而Fatima却不能反向找到Alice!固然,这样我认为是违反人类社会常识的。可是,谁让他是题目呢?
一道简单的题却覆盖了不少知识点,好比:while循环中的流程控制(continue),数组的基本方法(pop,forEach,push),for...in等等。
它的典型错误包括可是不限于:使用对象承载worklist,而后用for...in循环遍历worklist。
这样作的问题在于:for...in循环并无要求枚举对象的修改与当前循环保持一致。事实上,标准规范规定了:
“若是被枚举对象在枚举期间添加了新的属性,那么枚举期间并不能保证新添加的属性可以访问”。
这道题考察了面试者包括JS OOP在内的多项基础,尤为是后半道考察了候选者的思惟能力、反应能力。若是读者不能理解,欢迎留言问我。或者去查阅:《effective javascript》一书。
扯回原诗句,谈一下感悟,在天体的转动和岁月的轮回中,咱们分明的感觉到每个个体所拥有生命周期的单薄无力,在宏大的宇宙观中恐怕眇小不及沧海一粟。诗句的后半句拿出来共勉:“Hold infinity in the palm of your hand, and eternity in an hour 把无限放在你的手上,永恒在一刹那里收藏”。
在前端快速迭代发展的学习中,做为初学者,每每面对浩瀚的知识海洋望洋兴叹,此时基础即是那可以收藏“永恒和无限”的潘多拉魔盒。
本文对你有帮助?欢迎扫码加入前端学习小组微信群: