自己的面试会很实际, 几乎全部都是 coding, 很少会提到算法和一些抽象的概念. 自己提出的问题看似简单, 但是每一点都涉及到 JavaScript 的一些知识领域.
面试的时候并不建议使用白板, 通常希望面试者自己带上自己的笔记本, 或者就使用自己的. 我会将他们的代码运行, 并告知结果.
Object prototype
我起初会提出一个非常简单的问题就是定义一个函数 spacify , 将一个字符串作为参数传入, 然后返回一个字符串, 不过该字符串相对原有传入参数的变化是字母与字母之间多了一个空格.
spacify('hello world') // => 'h e l l o w o r l d'
虽然问题很简单, 但这却是一个很好的开始, 我们接下来的问题便可以围绕此展开, 尤其对于那些声称自己了解 JavaScript, 但实际却连一个函数都不会写的面试者高下立判.
正确的答案如下, 不过一些面试者或许会选择 for 循环, 当然这并没有错
- function spacify(str) {
- return str.split('').join(' ');
- }
接下来, 我会继续问如何将这个函数直接作用在一个字符串对象上.
'hello world'.spacify();
这个问题可以让我了解面试者对原型链的理解, 这个问题可以让彼此展开一些有讨论, 诸如直接在原型链上定义属性的危害等等. 实际期待结果:
- String.prototype.spacify = function(){
- return this.split('').join(' ');
- };
一般到这里我会让面试者讲讲函数声明和函数表达式的区别.
Arguments
接下来, 我会去了解面试者对于 arguments 的理解, 我们会要求面试者定一个 log 函数.
log('hello world');
函数类似实现一个简单的控制台输出, 在控制台输出传入的字符串. 一边面试者都会在定义的函数里直接写 console.log, 不过还是有更优秀的面试者会直接使用 apply.
- function log(msg){
- console.log(msg);
- }
接下来, 我会继续问如果我传入多个参数依旧输出一个字符串 , 我会提示面试者传入的 参数是不固定的, 我会暗示作者 console.log 实际上也接受多个参数.
log('hello', 'world');
不过我还是希望您的面试者现在已经想起 apply; 面试者可能会在 apply 和 call 上困惑, 这个时候我会做点小提示, 不过将 console 上下文传入也是非常重要的. 欢迎加入我们
- function log(){
- console.log.apply(console, arguments);
- };
接着我会继续追问, 如果我希望在那个输出的字符串前统一加上 (App) 这样的字符串, 类似于这样:
'(app) hello world'
这个问题明显会复杂很多, 面试者应该知道 arguments 是一个伪数组, 我们需要先将它转换成正常的数组, 我们可以使用 Array.prototype.slice, 代码如下:
- function log(){
- var args = Array.prototype.slice.call(arguments);
- args.unshift('(app)');
- console.log.apply(console, args);
- };
- Context
接下来我想了解面试者对于上下文以及 this 的理解, 我会给出下边的代码, 让面试者去解释 count 的值. 欢迎加入我们
- var User = {
- count: 1,
- getCount: function() {
- return this.count;
- }
- };
接下来我会给出下面的代码, 让面试者去回答应该输出的正确答案. 欢迎加入我们
- console.log(User.getCount());
- var func = User.getCount;
- console.log(func());
上面的例子中正确输出 1 和 undefined. 实际上很多面试者都会在这里跌倒. func 的上下文是 `Windows, 因此已经失去了 count 属性. 接下来我回继续追问面试者如何确保 func 的上下文始终都和 User 关联, 这样可以使输出的答案是 1. 欢迎加入我们
正确答案是使用 Function.prototype.bind, 代码如下:
- var func = User.getCount.bind(User);
- console.log(func());
这个时候我会让面试者去进行完善, 如果老的浏览器并不支持该方法, 我们应该怎样去兼容. 部分基础较差的面试者会比较纠结, 但是个人认为任何一位前端工程师都应该对 apply 和 call 有着较为深刻的理解. 欢迎加入我们
- Function.prototype.bind = Function.prototype.bind || function(context) {
- var self = this;
- return function(){
- return self.apply(context, arguments);
- };
- }
一个弹窗库
面试的最后 y 一部分, 我会要求面试者写点实际的东西. 这个非常有用, 足以了解前端的技术栈. 如果前面的问题回答的较为理想, 这个问题, 我会非常迅速的展开最后一个问题的考察.
虽然最终效果取决于面试者的实现, 但是这里依旧有足够的考察点.
最好不使用 position:absolute 而是 position:fixed, 这个时候即使窗体有滚动, 也可以很好的遮罩住全局. 我会提示面试者这样使用, 并且追问这两者的区别. 欢迎加入我们
- .overlay {
- position: fixed;
- left: 0;
- right: 0;
- bottom: 0;
- top: 0;
- background: rgba(0,0,0,.8);
- }
如何将里面的内容居中也是一个非常重要的考察点. 一些面试者会使用绝对定位, 而有的面试者则更擅长使用 JS.
- .overlay article {
- position: absolute;
- left: 50%;
- top: 50%;
- margin: -200px 0 0 -200px;
- width: 400px;
- height: 400px;
- }
我会继续问, 如何确保点击遮罩层时遮罩层是关闭的? 这个问题可以将我们的讨论落脚到 冒泡中来. 很多面试者都会直接将点击实践绑定到遮罩层上. 欢迎加入我们
$('.overlay').click(closeOverlay);
这个接下来可以工作了, 但是你会发现如果点击了遮罩层中的子元素, 遮罩层也会关闭. 解决方案是便是判断 event target , 并且保证 这个时间不会冒泡.
- $('.overlay').click(function(e){
- if (e.target == e.currentTarget)
- closeOverlay();
- });
尾声
当然前面的知识点仅仅是前端的一部分, 实际上你还可以问: 性能, html5 APIs, AMD vs CommonJS modules,constructors, 数据类型, 以及盒子模型. 我经常都会随着面试者的进行去选择相应的问题.
欢迎加入我们
结语
感谢您的观看, 如有不足之处, 欢迎批评指正.
获取资料
来源: http://www.qdfuns.com/article/51117/599af3b37ff3290788546822cf3dec30.html