Object.ObjectCreate = (proto, propertiesObject)=> {
// 对输入进行检测
if (typeof proto !== 'object' && typeof proto !== 'function' && proto !== null) {
throw new Error(`Object prototype may only be an Object or null:${proto}`);
}
// 新建一个对象
const result = {};
// 将该对象的原型设置为proto
Object.setPrototypeOf(result, proto);
// 将属性赋值给该对象
Object.defineProperties(result, propertiesObject);
// 返回该对象
return result;
}
3.2 Object assign()
function ObjectAssign(target, ...sources) {
// 对第一个参数的判断,不能为undefined和null
if (target === undefined || target === null) {
throw new TypeError('cannot convert first argument to object');
}
// 将第一个参数转换为对象(不是对象转换为对象)
const targetObj = Object(target);
// 将源对象(source)自身的所有可枚举属性复制到目标对象(target)
for (let i = 0; i < sources.length; i++) {
letsource = sources[i];
// 对于undefined和null在源角色中不会报错,会直接跳过
if (source !== undefined && source !== null) {
// 将源角色转换成对象
// 需要将源角色自身的可枚举属性(包含Symbol值的属性)进行复制
// Reflect.ownKeys(obj) 返回一个数组,包含对象自身的所有属性,不管属性名是Symbol还是字符串,也不管是否可枚举
const keysArray = Reflect.ownKeys(Object(source));
for (let nextIndex = 0; nextIndex < keysArray.length; nextIndex ++) {
const nextKey = keysArray[nextIndex];
// 去除不可枚举属性
const desc = Object.getOwnPropertyDescriptor(source, nextKey);
if (desc !== undefined && desc.enumerable) {
// 后面的属性会覆盖前面的属性
targetObj[nextKey] = source[nextKey];
}
}
}
}
return targetObj;
}
// 由于挂载到Object的assign是不可枚举的,直接挂载上去是可枚举的,所以采用这种方式
if (typeof Object.myAssign !== 'function') {
Object.defineProperty(Object, "myAssign", {
value : ObjectAssign,
writable: true,
enumerable: false,
configurable: true
});
}
Array.prototype.myMap = function(fn) {
// 判断输入的第一个参数是不是函数
if (typeof fn !== 'function') {
throw new TypeError(fn + 'is not a function');
}
// 获取需要处理的数组内容
const arr = this;
const len = arr.length;
// 新建一个空数组用于装载新的内容
const temp = new Array(len);
// 对数组中每个值进行处理
for (let i = 0; i < len; i++) {
// 获取第二个参数,改变this指向
let result = fn.call(arguments[1], arr[i], i, arr);
temp[i] = result;
}
// 返回新的结果
return temp;
}
4.2 filter
Array.prototype.myFilter = function (fn) {
if (typeof fn !== 'function') {
throw new TypeError(`${fn} is not a function`);
}
// 获取该数组
const arr = this;
// 获取该数组长度
const len = this.length >>> 0;
// 新建一个新的数组用于放置该内容
const temp = [];
// 对数组中每个值进行处理
for (let i = 0; i < len; i++) {
// 处理时注意this指向
const result = fn.call(arguments[1], arr[i], i, arr);
result && temp.push(arr[i]);
}
return temp;
}
4.3 reduce
Array.prototype.myReduce = function(fn) {
if (typeof fn !== 'function') {
throw new TypeError(`${fn} is not a function`);
}
const arr = this;
const len = arr.length >>> 0;
let value;// 最终返回的值
let k = 0;// 当前索引
if (arguments.length >= 2) {
value = arguments[1];
} else {
// 当数组为稀疏数组时,判断数组当前是否有元素,如果没有索引加一
while (k < len && !( k in arr)) {
k++;
}
// 如果数组为空且初始值不存在则报错
if (k >= len) {
throw new TypeError('Reduce of empty array with no initial value');
}
value = arr[k++];
}
while (k < len) {
if (k in arr) {
value = fn(value, arr[k], k, arr);
}
k++;
}
return value;
}