1.手写promise
// exector 执行器
function Promise1(exector) {
var that = this;
this.status = "pedding"; //设置状态
this.resolveParams = ""; //resolve返回的值
this.rejectParams = ""; //存储reject 返回的值
this.resolveFn = []; //存储then中成功的回调函数
this.rejectFn = []; //存储then中失败的回调函数
function resolve(value) {
//只有在pedding状态才执行 防止多次点击
if (that.status == "pedding") {
that.status = "resolved";
that.resolveParams = value;
that.resolveFn.forEach(fn => fn(value))
}
}
function reject(value) {
//只有在pedding状态才执行 防止多次点击
if (that.status == "pedding") {
that.status = "rejected";
that.rejectParams = value;
that.rejectFn.forEach(fn => fn(value))
}
}
//执行器捕获异常
try {
exector(resolve, reject);
} catch (e) {
reject(e)
}
}
Promise1.prototype.then = function (resolve1, reject1) {
var that = this;
//同步执行成功回调函数
if (this.status == "resolved") {
resolve1(that.resolveParams)
}
//同步执行失败回调函数
if (this.status == "rejected") {
reject1(that.rejectParams)
}
//异步情况时 保存回调函数
if (this.status == "pedding") {
this.resolveFn.push((val) => {
resolve1(val)
})
this.rejectFn.push((val) => {
reject1(val)
})
}
}
//测试
function test() {
return new Promise1((resolve, reject) => {
setTimeout(() => {
let val = Math.random();
if (val > 0.5) {
resolve('成功')
} else {
reject('失败')
}
}, 100)
})
}
test().then(res => {
console.log(res)
}, (err) => {
console.log(err)
})
2.数组和对象深拷贝
1.JSON.parse(JSON.stringify())
2.手写简易版
function deepCopy(obj) {
if (typeof obj !== "object"||!obj) {
return obj;
}
const result= Array.isArray(obj) ? [] : {};
for (let key in obj) {
result[key] = typeof obj[key] !== "object" ? obj[key] : deepCopy(obj[key]);
}
return result;
}
3.完整版
/**
* deep clone
* @param {[type]} parent object 需要进行克隆的对象
* @return {[type]} 深克隆后的对象
*/
const clone = parent => {
// 判断类型
const isType = (obj, type) => {
if (typeof obj !== "object") return false;
const typeString = Object.prototype.toString.call(obj);
let flag;
switch (type) {
case "Array":
flag = typeString === "[object Array]";
break;
case "Date":
flag = typeString === "[object Date]";
break;
case "RegExp":
flag = typeString === "[object RegExp]";
break;
default:
flag = false;
}
return flag;
};
// 处理正则
const getRegExp = re => {
var flags = "";
if (re.global) flags += "g";
if (re.ignoreCase) flags += "i";
if (re.multiline) flags += "m";
return flags;
};
// 维护两个储存循环引用的数组
const parents = [];
const children = [];
const _clone = parent => {
if (parent === null) return null;
if (typeof parent !== "object") return parent;
let child, proto;
if (isType(parent, "Array")) {
// 对数组做特殊处理
child = [];
} else if (isType(parent, "RegExp")) {
// 对正则对象做特殊处理
child = new RegExp(parent.source, getRegExp(parent));
if (parent.lastIndex) child.lastIndex = parent.lastIndex;
} else if (isType(parent, "Date")) {
// 对Date对象做特殊处理
child = new Date(parent.getTime());
} else {
// 处理对象原型
proto = Object.getPrototypeOf(parent);
// 利用Object.create切断原型链
child = Object.create(proto);
}
// 处理循环引用
const index = parents.indexOf(parent);
if (index != -1) {
// 如果父数组存在本对象,说明之前已经被引用过,直接返回此对象
return children[index];
}
parents.push(parent);
children.push(child);
for (let i in parent) {
// 递归
child[i] = _clone(parent[i]);
}
return child;
};
return _clone(parent);
};
3.继承的实现 原型链继承
子类实例化出来的对象拥有父类的属性和方法
子类实例化出来的对象属于子类,也属于父类
原型链继承金三句:
-
让子类实例化出来的对象拥有父类的属性
Person.apply(this,arguments) -
让子类拥有父类的所有方法
Student.prototype=Object.create(Person.prototype); -
找回丢失的构造器
Student.prototype.constructor=Student;
//定义一个父类
function Person(name,age){
this.name=name;
this.age=age;
}
Person.prototype.run=function(){
console.log(this.name+'正在散步')
}
//定义一个子类
function Student(name,age,score){
this.score=score;
//让子类实例化出来的对象拥有父类的属性 apply 和call都可以
Person.apply(this,arguments)
}
//让子类拥有父类的所有方法
Student.prototype=Object.create(Person.prototype);
//找回丢失的构造器
Student.prototype.constructor=Student;
Student.prototype.read=function(){
console.log(this.name+'正在看书')
}
let student1 = new Student('张三',20,100);
console.dir(student1 );
console.log(student1 instanceof Student); //true
console.log(student1 instanceof Person); //true
Object.create 原理
function create(proto) {
function F(){}
F.prototype = proto;
return new F();
}
4.new 操作符实现
- 它创建了一个全新的对象。
- 它会被执行[[Prototype]](也就是proto)链接。
- 它使this指向新创建的对象。。
- 通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上。
如果函数没有返回对象类型Object(包含Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用将返回该对象引用。
function New(Fn) {
let obj = {}
let arg = Array.prototype.slice.call(arguments, 1)
obj.__proto__ = Fn.prototype
obj.__proto__.constructor = Fn
Fn.apply(obj, arg)
return obj
}
5.实现instanceOf
function instance_of(left, R) {
//L 表示左表达式,R 表示右表达式
var O = R.prototype; // 取 R 的显示原型
left= left.__proto__; // 取left 的隐式原型
while (true) {
if (left === null) return false;
if (O === left){
// 这里重点:当 O 严格等于left 时,返回 true
return true;
}
left= left.__proto__;
}
}
6.解析 URL Params 为对象
function parseParam(url) {
const paramsStr = /.+\?(.+)$/.exec(url)[1]; // 将 ? 后面的字符串取出来
const paramsArr = paramsStr.split('&'); // 将字符串以 & 分割后存到数组中
let paramsObj = {};
// 将 params 存到对象中
paramsArr.forEach(param => {
if (/=/.test(param)) { // 处理有 value 的参数
let [key, val] = param.split('='); // 分割 key 和 value
val = decodeURIComponent(val); // 解码
val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字
if (paramsObj.hasOwnProperty(key)) { // 如果对象有 key,则添加一个值
paramsObj[key] = [].concat(paramsObj[key], val);
} else { // 如果对象没有这个 key,创建 key 并设置值
paramsObj[key] = val;
}
} else { // 处理没有 value 的参数
paramsObj[param] = true;
}
})
return paramsObj;
}
7.实现一个call
// 模拟 call bar.mycall(null);
//实现一个call方法:
Function.prototype.myCall = function(context) {
//此处没有考虑context非object情况
context.fn = this;
let args = [];
for (let i = 1, len = arguments.length; i < len; i++) {
args.push(arguments[i]);
}
context.fn(...args);
let result = context.fn(...args);
delete context.fn;
return result;
};