[关闭]
@yacent 2016-10-24T23:22:04.000000Z 字数 4948 阅读 862

美团二面

面试题目


2016.03.24

很惊喜自己上一轮有些没答得太好,还是幸运地进入到了美团的二面。在这里,应
该是要感谢当时给我面试的师兄吧,他人挺好的,然后面试完了还一直在 帮我分
析(可能刚好是遇到身为广东的师兄面试到广东小伙伴的缘由,觉得很兴奋吧。

好的,下面话不多说,咱们直接进入到面试过程中的问题。

首先还是万年不变的自我介绍环节,面了一些,发现自我介绍环节,其实就自己讲
讲自己的一些经历就好,其实面试官在这段时间会看你的简历,然后准备 问题,
亦或者如果你的自我介绍有亮点的地方,不妨你自己多讲讲,比如做了哪些好的项
目,有什么创新点的地方等等,都是可以主动讲出来的。
我基本上都只是讲我个人信息,然后大一到现在经历以及如何学习并且做过的一些
项目。(我觉得 面试官比较会喜欢 爱学习 爱思考 爱动手的孩子) 怎么表现出来
就是自己去琢磨吧,总有方法能够旁敲侧击告诉他,我爱学习爱思考

OK 面试题开始了


组件化

问:请你说一说对于组件化的理解,以及在项目中如何进行实现的。

大致说了一下组件化,我所理解的组件化就是比如一个电视,是有很多个小零件组
成的,每个小零件都是一个完整的东西,整个电视就由这些小零件拼合起来。具体
到页面上,就比如一个sidebar,单独出来,然后在文件当中写上相应的html,写上
一些样式以及js之后,这就是一个sidebar组件, 然后别的页面上需要改组件,只
需要进行拼凑就好了。(其实是因为自己并没有玩过组件化,所以会说的有点虚,
真不知道自己为何当初脑残写了个组件化 上去,后来发现是因为自己理解的组件
化和实际的组件化不同。好吧,真的不要给自己挖坑,不然会gg,一定要确保自己
写在上面的东西都要知道。然后 我又说了一些,可以实现组件化的框架,比如
vue.js、react、angular.js、component等等都可以实现。
这道题因为自己也没有对组件化特别深入,所以面试官也没有继续追问下去。


设计模式

问:
请你说说你所了解设计模式

 我当时就说了 工厂、单例、观察者模式,一定要说自己知道确切实现方式的 

会比较好,不要给自己挖坑。

单例模式(singleton)
实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了
再返回,这就确保了一个类只有一个实例对象

  1. var createMask = (function() {
  2. var mask;
  3. return function() {
  4. return mask || (mask =
  5. document.body.appendChild(document.createElement("div")));
  6. }
  7. })();

可以从上面看出,此处用了一个简单的闭包,将mask包起来,对于createMask函数
来讲,其为封闭的。
我们可以修改一下,将单例模式修改为另外一种模式 桥接模式,即函数作为
参数传入,具体如下

  1. var singleton = function(fn) {
  2. var result;
  3. return function() {
  4. return result || (result = fn.apply(this, arguments));
  5. }
  6. }
  7. var createMask = singleton(function() {
  8. return document.body.appendChild(document.createElement("div"));
  9. });

工厂模式
简单工厂模式是由一个方法来决定到底要创建哪个类的实例, 而这些实例经常都拥
有相同的接口. 这种模式主要用在所实例化的类型在编译期并不能确定, 而是在
执行期决定的情况。 说的通俗点,就像公司茶水间的饮料机,要咖啡还是牛奶取
决于你按哪个按钮。

  1. function createPerson(name, age, job) {
  2. var o = new Object();
  3. o.name = name;
  4. o.age = age;
  5. o.job = job;
  6. o.sayName = function() {
  7. alert(this.name);
  8. };
  9. return o;
  10. }
  11. var person1 = createPerson("Nic", 29, "teacher");
  12. var person2 = createPerson("Yic", 21, "doctor");

工厂模式适用的场景:
1. 对象的构建复杂、繁琐
2. 需要依赖具体环境创建不同的实例
3. 处理大量具有相同属性的小对象

观察者模式(发布者-订阅者模式)
主题负责发布事件,同时观察者通过订阅这些事件来观察该主体
在我们所接触的事件,即为一种观察者模式

  1. // div为发布者,onclick事件为订阅者
  2. div.onclick = function() {
  3. alert("click");
  4. }

我们为什么要用观察者模式呢,主要是可以实现松散耦合的代码,什么意思?就是
主体和订阅者之间是相互独立的,其二者可以独立运行。

举个例子说明一下,使用观察者模式的好处。如下

某团队正在开发一个H5的游戏,游戏开始前,会先进行一些图片的加载,图片加在
完成后,会进行地图的加载以及Gamer模块的记载,具体代码如下

  1. loadImage(imgAry, function() {
  2. Map.init();
  3. Gamer.init();
  4. });

然后,需求改变了,需要再给游戏添加上声音的功能,可是,写该模块的同事去外
地旅游了,于是就要打电话给他,问loadImage的函数写在哪啊,能不能 改一下,
改了之后有没有副作用……此时,代码又会如下,但是心中是各种不淡定,不知道会
不会发生什么问题。

  1. loadImage(imgAry, function() {
  2. Map.init();
  3. Gamer.init();
  4. Sound.init();
  5. });
 要是采取观察者模式来进行写这个东西,就不关心会发生什么改变,对事件 

进行监听并且在合适的时候触发该事件即可

  1. loadImage.addHandler("ready", function() {
  2. Map.init();
  3. });
  4. loadImage.fire("ready")
 但是观察者模式从概念上来说是简单的,就是添加一个观察的以及触发的事 

件,但是具体实现呢?我比较喜欢用用自定义事件来模拟实现 观察者模式,如下

  1. function EventTarget() {
  2. this.handlers = {};
  3. }
  4. EventTarget.prototype = {
  5. constructor: EventTarget,
  6. addHandler: function(type, handler) {
  7. if (typeof this.handlers[type] == "undefined") {
  8. this.handlers[type] = []
  9. }
  10. this.handlers[type].push(handler);
  11. },
  12. fire: function(event) {
  13. if (!event.target) {
  14. event.target = this;
  15. }
  16. if (this.handlers[event.type] instanceof Array) {
  17. var handlers = this.handlers[event.type];
  18. for (var i = 0, len = handlers.length; i < len; i++) {
  19. handlers[i](event);
  20. }
  21. }
  22. },
  23. remove: function(type, handler) {
  24. if (this.handlers[type] instanceof Array) {
  25. var handlers = this.handlers[type];
  26. for (var i = 0, len = handlers.length; i < len; i++) {
  27. if (handlers[i] === handler) {
  28. break;
  29. }
  30. }
  31. handlers.splice(i, 1);
  32. }
  33. }
  34. };

推荐看:http://blog.jobbole.com/29454/ 或者看原著《Javascript设计模式》


deepEquals

问:
我现在出一道题目给你,然后具体如下

  1. function deepEqual() {
  2. // code here
  3. }
  4. // 测试
  5. deepEqual({a:1}, {a:1}); // true
  6. deepEqual([1,2], [1, 2]); // true
  7. deepEqual([1, {a:1}], [1, {a:1}]); // true

这题出给我之后,大致理解一下题目,就是说,要自己实现一个deepEqual的函
数,然后能够判别两个object是相等与否,两个array 相等否,以及array当中是
可以嵌套object的,object当中也是可以嵌套object的。

短时间内,我觉得是很难写完整的,关键思想是要怎么处理 → 嵌套
要体现出思想我觉得就OK了

  1. function deepEqual(a, b) {
  2. // produce Array
  3. if (isArray(a) && isArray(b)) {
  4. return isSameArray(a, b);
  5. }
  6. // produce object
  7. if (isObject(a) && isObject(b)) {
  8. return isSameObject(a, b);
  9. }
  10. if (a.toString() === b.toString()) {
  11. return true;
  12. }
  13. return false;
  14. }
  15. function isArray(a) {
  16. return (Object.prototype.toString.call(a) === "[object Array]");
  17. }
  18. function isObject(a) {
  19. return (typeof a === "object");
  20. }
  21. function getKeys(obj) {
  22. var keys = [];
  23. for (var k in obj) {
  24. keys.push(k);
  25. }
  26. return keys;
  27. }
  28. function isSameArray(a, b) {
  29. if (a.length !== b.length) {
  30. return false;
  31. }
  32. for (var i = 0, len = a.length; i < len; i++) {
  33. if (!deepEqual(a[i], b[i])) {
  34. return false;
  35. }
  36. }
  37. return true;
  38. }
  39. function isSameObject(a, b) {
  40. var aKeys = getKeys(a);
  41. var bKeys = getKeys(b);
  42. if (aKeys.length !== bKeys.length) {
  43. return false;
  44. }
  45. //sort
  46. aKeys.sort();
  47. bKeys.sort();
  48. for (var i = 0, len = aKeys.length; i < len; i++) {
  49. var k = aKeys[i];
  50. // recursive deep equal
  51. if (!deepEqual(a[k], b[k])) {
  52. return false;
  53. }
  54. }
  55. return true;
  56. }
  57. // 测试
  58. deepEqual({a:1}, {a:1}); // true
  59. deepEqual([1,2], [1, 2]); // true
  60. deepEqual([1, {a:1}], [1, {a:1}]); // true

CSS垂直水平居中

问:
我要实现一个元素的垂直水平都居中,你会怎么去实现。

 这道题应该还是中规中矩的,就挺正常的经典考题,我经常使用的是两种方 

法,如下

  1. ////// html //////
  2. <div class="outer">
  3. <div class="inner"></div>
  4. </div>
  5. ////// css ///////
  6. .outer {
  7. position: relative;
  8. width: 300px;
  9. height: 300px;
  10. border: 1px solid black;
  11. }
  12. /* method 1*/
  13. .inner {
  14. position: absolute;
  15. top: 50%;
  16. left: 50%;
  17. transform: translate(-50%, -50%);
  18. }
  19. /* method 2*/
  20. .inner {
  21. position: absolute;
  22. top: 0;
  23. bottom: 0;
  24. left: 0;
  25. right: 0;
  26. margin: auto;
  27. }

以上两种方法是我平常所最爱使用过的垂直水平居中的办法,当然还有许许多多其
他的办法,比如知道确切width和height的时候,也可以用 margin来进行调整固定
的长度。
如果是行内元素的垂直水平居中,比较简单,只需要用 text-align以及
line-height两个属性就可以完成了。具体可以自己查询一下。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注