@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)
实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了
再返回,这就确保了一个类只有一个实例对象
var createMask = (function() {
var mask;
return function() {
return mask || (mask =
document.body.appendChild(document.createElement("div")));
}
})();
可以从上面看出,此处用了一个简单的闭包,将mask包起来,对于createMask函数
来讲,其为封闭的。
我们可以修改一下,将单例模式修改为另外一种模式 桥接模式,即函数作为
参数传入,具体如下
var singleton = function(fn) {
var result;
return function() {
return result || (result = fn.apply(this, arguments));
}
}
var createMask = singleton(function() {
return document.body.appendChild(document.createElement("div"));
});
工厂模式
简单工厂模式是由一个方法来决定到底要创建哪个类的实例, 而这些实例经常都拥
有相同的接口. 这种模式主要用在所实例化的类型在编译期并不能确定, 而是在
执行期决定的情况。 说的通俗点,就像公司茶水间的饮料机,要咖啡还是牛奶取
决于你按哪个按钮。
function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
alert(this.name);
};
return o;
}
var person1 = createPerson("Nic", 29, "teacher");
var person2 = createPerson("Yic", 21, "doctor");
工厂模式适用的场景:
1. 对象的构建复杂、繁琐
2. 需要依赖具体环境创建不同的实例
3. 处理大量具有相同属性的小对象
观察者模式(发布者-订阅者模式)
主题负责发布事件,同时观察者通过订阅这些事件来观察该主体
在我们所接触的事件,即为一种观察者模式
// div为发布者,onclick事件为订阅者
div.onclick = function() {
alert("click");
}
我们为什么要用观察者模式呢,主要是可以实现松散耦合的代码,什么意思?就是
主体和订阅者之间是相互独立的,其二者可以独立运行。
举个例子说明一下,使用观察者模式的好处。如下
某团队正在开发一个H5的游戏,游戏开始前,会先进行一些图片的加载,图片加在
完成后,会进行地图的加载以及Gamer模块的记载,具体代码如下
loadImage(imgAry, function() {
Map.init();
Gamer.init();
});
然后,需求改变了,需要再给游戏添加上声音的功能,可是,写该模块的同事去外
地旅游了,于是就要打电话给他,问loadImage的函数写在哪啊,能不能 改一下,
改了之后有没有副作用……此时,代码又会如下,但是心中是各种不淡定,不知道会
不会发生什么问题。
loadImage(imgAry, function() {
Map.init();
Gamer.init();
Sound.init();
});
要是采取观察者模式来进行写这个东西,就不关心会发生什么改变,对事件
进行监听并且在合适的时候触发该事件即可
loadImage.addHandler("ready", function() {
Map.init();
});
loadImage.fire("ready")
但是观察者模式从概念上来说是简单的,就是添加一个观察的以及触发的事
件,但是具体实现呢?我比较喜欢用用自定义事件来模拟实现 观察者模式,如下
function EventTarget() {
this.handlers = {};
}
EventTarget.prototype = {
constructor: EventTarget,
addHandler: function(type, handler) {
if (typeof this.handlers[type] == "undefined") {
this.handlers[type] = []
}
this.handlers[type].push(handler);
},
fire: function(event) {
if (!event.target) {
event.target = this;
}
if (this.handlers[event.type] instanceof Array) {
var handlers = this.handlers[event.type];
for (var i = 0, len = handlers.length; i < len; i++) {
handlers[i](event);
}
}
},
remove: function(type, handler) {
if (this.handlers[type] instanceof Array) {
var handlers = this.handlers[type];
for (var i = 0, len = handlers.length; i < len; i++) {
if (handlers[i] === handler) {
break;
}
}
handlers.splice(i, 1);
}
}
};
推荐看:http://blog.jobbole.com/29454/ 或者看原著《Javascript设计模式》
deepEquals
问:
我现在出一道题目给你,然后具体如下
function deepEqual() {
// code here
}
// 测试
deepEqual({a:1}, {a:1}); // true
deepEqual([1,2], [1, 2]); // true
deepEqual([1, {a:1}], [1, {a:1}]); // true
这题出给我之后,大致理解一下题目,就是说,要自己实现一个deepEqual的函
数,然后能够判别两个object是相等与否,两个array 相等否,以及array当中是
可以嵌套object的,object当中也是可以嵌套object的。
短时间内,我觉得是很难写完整的,关键思想是要怎么处理
→ 嵌套
要体现出思想我觉得就OK了
function deepEqual(a, b) {
// produce Array
if (isArray(a) && isArray(b)) {
return isSameArray(a, b);
}
// produce object
if (isObject(a) && isObject(b)) {
return isSameObject(a, b);
}
if (a.toString() === b.toString()) {
return true;
}
return false;
}
function isArray(a) {
return (Object.prototype.toString.call(a) === "[object Array]");
}
function isObject(a) {
return (typeof a === "object");
}
function getKeys(obj) {
var keys = [];
for (var k in obj) {
keys.push(k);
}
return keys;
}
function isSameArray(a, b) {
if (a.length !== b.length) {
return false;
}
for (var i = 0, len = a.length; i < len; i++) {
if (!deepEqual(a[i], b[i])) {
return false;
}
}
return true;
}
function isSameObject(a, b) {
var aKeys = getKeys(a);
var bKeys = getKeys(b);
if (aKeys.length !== bKeys.length) {
return false;
}
//sort
aKeys.sort();
bKeys.sort();
for (var i = 0, len = aKeys.length; i < len; i++) {
var k = aKeys[i];
// recursive deep equal
if (!deepEqual(a[k], b[k])) {
return false;
}
}
return true;
}
// 测试
deepEqual({a:1}, {a:1}); // true
deepEqual([1,2], [1, 2]); // true
deepEqual([1, {a:1}], [1, {a:1}]); // true
CSS垂直水平居中
问:
我要实现一个元素的垂直水平都居中,你会怎么去实现。
这道题应该还是中规中矩的,就挺正常的经典考题,我经常使用的是两种方
法,如下
////// html //////
<div class="outer">
<div class="inner"></div>
</div>
////// css ///////
.outer {
position: relative;
width: 300px;
height: 300px;
border: 1px solid black;
}
/* method 1*/
.inner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* method 2*/
.inner {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
以上两种方法是我平常所最爱使用过的垂直水平居中的办法,当然还有许许多多其
他的办法,比如知道确切width和height的时候,也可以用 margin来进行调整固定
的长度。
如果是行内元素的垂直水平居中,比较简单,只需要用 text-align以及
line-height两个属性就可以完成了。具体可以自己查询一下。