本文已参加「新人创造礼」活动,一同开启创造之路。
本文参加了由大众号@若川视界建议的每周源码共读活动, 点击了解概况一同参加。
【若川视界 x 源码共读】第19期 | axios 东西函数 点击了解本期概况一同参加。
这篇文章没有依照直接贴上源码来剖析的方式去写,主要原因是原文章中已经剖析的很详细了;另一方面,感觉经过问答的方式思考问题学习效果更好.
这次经过答复问题的方式来巩固自己的学习效果.
来自@NewName的问题:
看完源码,又看到了谈论区有大佬抛出问题.
感觉这些问题和自己阅览源码时遇到的问题很类似,故用这些问题来查验自己的学习效果.
1.js中怎么判别变量属于哪种引用数据类型(例如:Array, Function等)
运用instanceof办法
[] instanceof Array; // true
{} instanceof Object; // true
2.怎么判别变量是否为文件(File)?
Object.prototype.toString.call(file) == '[object File]'
3.是否了解Buffer,ArrayBuffer?
待弥补
4.怎么判别变量是否为FormData?
FormData用来以键值对的形式发送表单数据.
// 运用构造函数来创建实例
var formData = new FormData();
// append添加数据
formData.append(key,value);
// 经过ajax来发送数据
var request = new XMLHttpRequest();
request.open('GET','https://www.baidu.com');
request.send(formData);
判别办法为:
- 运用instanceof
- 运用Object.prototype.toString.call办法
formData instanceof FormData //true
Object.prototype.toString.call(formData) //[object FormData]
5.怎么运用正则去掉字符串中的空格?
字符串中的trim办法能够去除首尾中指定的字符.
源码中的正则表达式用来去除字符串首位的空白字符:
str.replace(/^s+|s+$/g, '');
若想去除字符串中的所有空格,直接匹配s
即可
const str = ' 1 2 3 ';
const regex = /s/g;
console.log(str.replace(regex,'')); // '123'
6.编写一个既能够遍历数组又能够遍历目标的办法?
直接看源码遍历的办法:
function forEach(obj, fn) {
if (obj === null || typeof obj === 'undefined') {
return;
}
if (typeof obj !== 'object') {
obj = [obj];
}
if (isArray(obj)) {
for (var i = 0, l = obj.length; i < l; i++) {
fn.call(null, obj[i], i, obj);
}
} else {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
fn.call(null, obj[key], key, obj);
}
}
}
}
- 传入为null与undefined类型不做遍历
- 非目标类型包裹一层数组(转换成数组)
- 假如类型为数组,直接for循环遍历,每次循环调用传入的函数fn
- 假如类型为目标,先进行if判别.for…in是能够遍历到目标原型上的特点的,句子
Object.prototype.hasOwnProperty.call(obj, key)
能够避免遍历到目标原型上的特点.然后进行函数调用.
7.怎么兼并可变个数的目标?
看源码:
function merge(/* obj1, obj2, obj3, ... */) {
var result = {};
function assignValue(val, key) {
if (isPlainObject(result[key]) && isPlainObject(val)) {
result[key] = merge(result[key], val);
} else if (isPlainObject(val)) {
result[key] = merge({}, val);
} else if (isArray(val)) {
result[key] = val.slice();
} else {
result[key] = val;
}
}
for (var i = 0, l = arguments.length; i < l; i++) {
forEach(arguments[i], assignValue);
}
return result;
}
- 遍历传入的每一个参数,调用
forEach
办法;相当于每一个传入的目标都调用了assignValue
办法.(在forEach办法中,默以为assignValue函数传入参数,此刻参数val为目标特点值,key为目标特点名) - 假如result成果为空,且val为目标,进行递归,以原result为根本
- 假如result成果不为空,且val为目标,以空目标为根本
- 假如是数组,运用slice来返回新数组
- 假如是其它类型,直接赋值
8.js中怎么对数组进行深复制都有哪些办法?(slice(), 拜见merge函数完成过程)
感觉这个问题问的是: 怎么避免数组产生引用传递?
result[key] = val.slice();
数组的slice办法将返回一个浅复制后的新数组,假如直接将数组赋值给目标,将会形成引用传递
,运用slice办法能够处理这个问题.