2017 阿里前端笔试题

一、选择题

1. 下列程序运行的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
let obj = Object.create({name: 'King'});
function foo(obj){
Object.setPrototypeOf(obj, null);
return obj;
}
console.log(obj === foo(obj)); // true

let obj = [1,2,3];
function foo(val){
val = [1,2,3];
return val;
}
console.log(obj === foo(obj)); // false

let obj = 1;
function foo(val){
val += 1;
return val;
}
console.log(obj === foo(obj)); // false

let obj = {bar: 1};
function foo(val){
val.bar += 1;
return val
}
console.log(obj === foo(obj)); // true

let obj = [1,2,3];
function foo(val){
const newVal = val.map(num => num * 2);
return newVal;
}
console.log(obj === foo(obj)); // false

let obj = [1,2,3];
function foo(val){
return val.sort();
}
console.log(obj === foo(obj)); // true

这里主要考察的引用对象的引用地址是否相同

2. 事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<body>
<div id="J_container">
<div id="div2">
<div id="div1">点我</div>
</div>
</div>
<script>
var div1 = document.getElementById('div1');
var div2 = document.getElementById('div2');
div1.addEventListener('click', () => {console.log('a')}, true);
div2.addEventListener('click', () => {console.log('b')});
div1.addEventListener('click', () => {console.log('c')}, false);
div2.addEventListener('click', () => {console.log('d')}, true);
</script>
</body>

输出的顺序是: d a c b
addEventListener 的第三个参数,是表示事件冒泡还是捕获
点击 div1 之后,事件在 div2 和 div1 处被捕获,打印出 d, a,
之后事件开始向上冒泡,才出现了 c, b

第一道编程题:

要求:
0.png
我的答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function cycleDetector(obj){
let stack = [];
let res = false;
let _incircle = function(item){
let len = stack.length;
for( let y = 0; y < len; y++){
if( item === stack[y]){
return true;
}
}
return false;
}
let _read = function(_obj){
for ( let pro in _obj ){
if( _obj[pro] instanceof Object ){
if ( !_incircle(_obj[pro]) ){
stack.push(_obj[pro]);
_read(_obj[pro]);
}else{
res = true;
}
}
}
};
_read(obj);
return res;
}

类似与数组去重的思想,遍历这个 obj,如果有存在,就证明存在环

第二道编程题

要求:
1.png
我的答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 class EventEmitter {
/* 在此处填写实现 */
constructor(){
this.eventlist = {};
this.onceEventlist = {};
}
fire(obj){
const { type, value } = obj;
let _run = 1;
let _find = function(list){
for(let i in list){
if(i === type){
for(let j in list[i]){
list[i][j](value);
if( _run ){
delete list[i];
}
}
}
}
_run = 0;
};
_find(this.onceEventlist);
_find(this.eventlist);
}
on(event, fn){
this.eventlist[event] = {};
this.eventlist[event][fn.name] = fn;
}
off(event, fn){
if(this.eventlist[event]){
delete this.eventlist[event][fn.name];
}
}
once(event, fn){
this.onceEventlist[event] = {};
this.onceEventlist[event][fn.name] = fn;
}
}

const emitter = new EventEmitter();

const handler = function(evt) {
console.log(1, evt);
};
emitter.on('foo', handler);

emitter.once('foo', function(evt) {
console.log(2, evt);
});

emitter.fire({ type: 'foo', value: 'hello' });
emitter.fire({ type: 'foo', value: 'world' });
emitter.off('foo', handler);
emitter.fire({ type: 'foo', value: 'test' });

一个简易的订阅发布者模式

三、其它

一道模板解析习题
3.png
通过正则解析来做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var template = function(str) {
var replace = {};
var result;
var newStr = str;
var re = new RegExp('\\<\\%\\=\\w+\\%\\>','g');
while((result = re.exec(str)) !== null){
var _re = new RegExp('\\w+','g');
var item = result[0].match(_re)[0];
replace[item] = {};
replace[item].origin = result[0];
}
return function(obj) {
for(var i in obj){
if(replace[i]){
str = str.replace(replace[i].origin, obj[i]);
}
}
return str;
}
}