1 对valueOf()的的认识,数据类型转换
var a = false
var b = new Boolean()
console.log(a.valueOf() === a)
console.log(b.valueOf() === b)

2 实现一个add方法add(1,2) 和add(1)(2)都输入3的认识的理解, 考点考点:柯里化的运用

1
2
3
4
5
6
7
8
9
10
11
12
13
function add () {
var args = [].slice.call(arguments);

var fn = function () {
var arg_fn = [].slice.call(arguments);
return add.apply(null, args.concat(arg_fn));
}

fn.valueOf = function() {
return args.reduce((a, b) => a + b);
}
return fn;
}

扩展知识点:

(1)引用类型转换为字符串

  • 优先调用toString方法(如果有),看其返回结果是否是原始类型,如果是,转化为字符串,返回。
  • 否则,调用valueOf方法(如果有),看其返回结果是否是原始类型,如果是,转化为字符串,返回。
  • 其他报错。

(2)引用类型转化为数字

  • 优先调用valueOf方法(如果有),看其返回结果是否是原始类型,如果是,转化为数字,返回。
  • 否则,调用toString方法(如果有),看其返回结果是否是原始类型,如果是,转化为数字,返回。
  • 其他报错。

3 webpack 常用的插件有哪些?如何去掉重复的模块?
答:new webpack.optimize.DedupePlugin() 是查找相等或近似的模块,避免在最终生成的文件中出现重复的模块,比如可以用它去除依赖中重复的插件;
new webpack.optimize.OccurenceOrderPlugin() 是为组件和模块分配ID,通过这个插件webpack可以分析和优先考虑使用最多的模块,并为它们分配最小的ID,通过分析ID,可以建议降低总文件的大小。

4 vuex是什么,如何理解?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态

5 实现一个map方法,map(obj, function (value, index) {}), 如果obj是数组的话, 如果是对象的话,返回key和value

6 实现一个判断类型的方法

1
2
3
4
5
function isType(type) {
return function(obj) {
return Object.prototype.toString.call(obj) === `[object ${type}]
}
}

7 自定义低版本的bind方法兼容,

注意点: bind方法返回的是一个方法。

1
2
3
4
5
6
7
8
9
10
11
if (!Function.prototype.bind) {
Function.prototype.bind = function(context) {
let self = this,
slice = Array.prototype.slice,
args = slice.call(arguments);

return function () {
return self.apply(context, args.slice(1).concat(arguments));
}
};
}

8 节流函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function throttle (fn, wait) {
let _fn = fn, // 保存需要被延迟的函数引用
timer,
flags = true; // 是否首次调用

return function() {
let args = arguments,
self = this;

if (flags) { // 如果是第一次调用不用延迟,直接执行即可
_fn.apply(self, args);
flags = false;
return flags;
}
// 如果定时器还在,说明上一次还没执行完,不往下执行
if (timer) return false;

timer = setTimeout(function() { // 延迟执行
clearTimeout(timer); // 清空上次的定时器
timer = null; // 销毁变量
_fn.apply(self, args);
}, wait);
}
}

9 分时函数

理解: 我们如果一次获得了很多数据(比如有10W数据),然后在前端渲染的时候会卡到爆,浏览器那么温柔的物种都会起来骂娘了

所以在处理这么多数据的时候,我们可以选择分批进行,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function timeChunk(data, fn, count = 1, wait) {
let obj, timer;

function start() {
let len = Math.min(count, data.length);
for (let i = 0; i < len; i++) {
val = data.shift(); // 每次取出一个数据,传给fn当做值来用
fn(val);
}
}

return function() {
timer = setInterval(function() {
if (data.length === 0) { // 如果数据为空了,就清空定时器
return clearInterval(timer);
}
start();
}, wait); // 分批执行的时间间隔
}
}

10 惰性加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let addEvent = function(ele, type, fn) {
if (window.addEventListener) {
addEvent = function(ele, type, fn) {
ele.addEventListener(type, fn, false);
}
} else if (window.attachEvent) {
addEvent = function(ele, type, fn) {
ele.attachEvent('on' + type, function() {
fn.call(ele)
});
}
}

addEvent(ele, type, fn);
};

11 http1.0 和http 2.0有什么区别?

答:多路复用、服务器推送、首部压缩

12 http请求,请求头和响应头都有什么信息?

(1)request headers 请求头

  • Accept: 指定客户端能够接收的内容类型

  • Accept-Encoding: 指定客户端浏览器可以支持的web服务器返回内容压缩编码类型

  • Accept-Language: 客户端可以接受的语言

  • Connection: 持久连接, keep-live

  • Content-type: (1) ‘application/x-www-form-urlencoded’: 表单数据向服务器提交时所采用的编码类型 (2) multipart/form-data: 在文件上载时,所使用的编码类型应当是“multipart/form-data”,它既可以发送文本数据,也支持二进制数据上传

当提交为表单单数据时,可以使用“application/x-www-form-urlencoded”;当提交的是文件时,就需要使用“multipart/form-data”编码类型。

  • cookie : 浏览器端cookie。

  • User-Agent: 客户端信息

  • x-Requested-With: 是否为同步请求。如果为XMLHttpRequest,则为 Ajax 异步请求。如果为null则为传统同步请求

(2)响应头Response Header

  • Cache-Control: 告诉所有的缓存机制是否可以缓存及哪种类型

  • Content-Type: 返回内容的MIME类型

  • Expires: 响应过期的日期和时间

  • Last-Modified: 请求资源的最后修改时间

13 数组去重的方法

14 require 和import的区别

javascript 模块规范: CommonJS 和 AMD

(1) 适用于服务端的模块common.js
在CommonJS中,暴露模块使用module.exports和exports

(2) 适用于客户端的模块规范 AMD 和CMD
AMD: require.js

CMD: sea.js

CMD与AMD区别

AMD和CMD最大的区别是对依赖模块的执行时机处理不同,而不是加载的时机或者方式不同,二者皆为异步加载模块。

AMD依赖前置,js可以方便知道依赖模块是谁,立即加载;

而CMD就近依赖,需要使用把模块变为字符串解析一遍才知道依赖了那些模块,这也是很多人诟病CMD的一点,牺牲性能来带来开发的便利性,实际上解析模块用的时间短到可以忽略。

现在的规范

ES6中的module

1
2
3
4
5
// 错误演示
export 1; // 绝对不可以

var a = 100;
export a;

15 当我们 new操作的, 都发生了什么?

  • 创建空对象,并继承原型对象

  • 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象)

  • 执行构造函数中的代码(为这个新对象添加属性

  • 如果返回值是object则返回新对象,否则返回object

var obj = new Base();

new 操作干了什么事情?

1
2
3
var obj  = {};
obj.__proto__ = Base.prototype;
Base.call(obj);

第一行,我们创建了一个空对象obj
第二行,我们将这个空对象的proto成员指向了Base函数对象prototype成员对象
第三行,我们将Base函数对象的this指针替换成obj,然后再调用Base函数,于是我们就给obj对象赋值了一个id成员变量,这个成员变量的值是”base”,关于call函数的用法。

16 写一个继承的例子

1
2
3
4
5
6
7
8
9
function Animal () {
this.name = 'shen'
}
function Animal2 () {
Animal.call(this)

}
console.log(new Animal2())
缺点:

17 如何判断一个变量是对象还是数组?

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
//1 判断是否是数组还是对象(兼容性最好)
function isObjArr(value) {
if (Object.prototype.toString.call(value) === "[object Array]") {
console.log(‘value是数组’)
} else if (Object.prototype.toString.call(value)==='[object Object]') {
console.log('value是对象')
} else {
console.log('value既不是数组也不是对象')
}
}
// 2 typeof 判断类型

console.log(typeof null) // object

console.log(typeof []) // object

console.log(typeof a) // undefined

console.log(typeof undefined) // undefined

//3 instanceof操作符

var arr = [1,2,3,1];
console.log(arr instanceof Array); // true

// 4 对象的constructor属性

var arr = [1,2,3]
console.log(arr.constructor === Array) // true


// 5 Array.isArray()

// 有一个当前的判断数组的最佳写法:

function isArrayFn (value) {
if (typeof Array.isArray === 'function') {
return Array.isArray(value)
} else {
return Obeject.prototype.toString.call(value) === '[object Array]'
}
}

18 ES5的继承和ES6的继承有什么区别?

19 css3有哪些新的属性?

  • border-radius
  • box-shadow
  • border-image
  • background-size
  • background-image
  • linear-gradient // 线性渐变
  • radial-gradient // 径向渐变
  • text-shadow
  • @font-face
  • transform
  • rotateX rotateY
  • transition
  • animation

20 如何对一个数组去重?
(1)ES6的set方法
let unique= […new Set(array)]

(2)遍历,将值添加到新数组,用indexOf()判断值是否存在,已存在就不添加,达到去重效果。

(3) 遍历,将数组的值添加到一个对象的属性名里,并给属性赋值,对象不能添加相同属性名,以这个为依据可以实现数组去重,然后用Object.keys(对象)返回这个对象可枚举属性组成的数组,这个数组就是去重后的数组。

21 翻转一个字符串