C:\Users\Administrator\Desktop\手写\01_instanceOf.js
function instance_of(target, origin) {
let targetP = target.__proto__;
let originP = origin.prototype;
while (true) {
if (targetP === originP) return true;
if (targetP === null) return false;
targetP = targetP.__proto__;
}
}
console.log([1] instanceof Array);
console.log(instance_of([1], Array));
console.log(instance_of([1], Object));
console.log(instance_of([1], Map));
C:\Users\Administrator\Desktop\手写\02_模拟new关键字.js
let arr = objectFactory(Array, 'cxk', '18');
console.log(arr);
function objectFactory() {
// 创建一个权限的对象
const obj = new Object();
// 取出参数的第一项,为了得到构造函数
const Constructor = [].shift.call(arguments);
// 对象隐式原型指向构造器的显示原型
obj.__proto__ = Constructor.prototype;
// arguments经过前面的shift方法,实际上已经少了第一个参数
const ret = Constructor.apply(obj, arguments);
// 如果构造函数返回时object,则创建成功返回对象
return typeof ret === 'object' ? ret : obj;
}
C:\Users\Administrator\Desktop\手写\03_继承.js
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.eating = function () {
console.log('I am eating');
};
function Student(name, age, grade) {
Person.call(this, name, age);
this.grade = grade;
}
// 修改子类构造函数的 显示原型,为父类的一个实例对象,为的是使用父类原型对象中的方法
// Student.prototype = new Person();
Student.prototype = Object.create(Person.prototype);
// 子类原型对象,要指会原来的子类构造函数本身
Student.prototype.constructor = Student;
Student.prototype.study = function () {
console.log('I am studying');
};
const stu = new Student('Alice', 19, '一年级');
console.log(stu);
stu.eating();
C:\Users\Administrator\Desktop\手写\04_继承_class关键字.js
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
eating() {
console.log('I am eating');
}
}
class Student extends Person {
constructor(name, age, grade) {
super(name, age);
this.grade = grade;
}
studying() {
console.log('I am studying');
}
}
const stu = new Student('Alice', 19, '一年级');
console.log(stu);
stu.eating();
C:\Users\Administrator\Desktop\手写\05_手写call函数.js
Function.prototype.myCall = function (context, ...args) {
let cxt = context || window;
//将当前被调用的方法定义在cxt.func上.(为了能以对象调用形式绑定this)
//新建一个唯一的Symbol变量避免重复
let func = Symbol();
// this 表示前面发起调用的那个函数对象
cxt[func] = this;
console.log(args);
args = args ? args : [];
//以对象调用形式调用func,此时this指向cxt 也就是传入的需要绑定的this指向
const res = args.length > 0 ? cxt[func](...args) : cxt[func]();
//删除该方法,不然会对传入对象造成污染(添加该方法)
delete cxt[func];
// return res 是为了拿到返回值,万一有的函数有返回值呢
return res;
};
const obj = { name: 'Alice' };
function foo(value1, value2) {
console.log('this is foo ↓↓↓↓↓' + value1 + value2);
console.log(this);
return '我是返回值';
}
foo.myCall(obj, 'hello hahahahahaha', 'heiheihei');
C:\Users\Administrator\Desktop\手写\06_手写apply方法.js
Function.prototype.myApply = function (context = window, args = []) {
let sy = Symbol();
context[sy] = this;
let res = args.length > 0 ? context[sy](...args) : context[sy]();
return res;
};
const obj = { name: 'Alice' };
function foo(value1, value2) {
console.log('this is foo ↓↓↓↓↓' + value1, value2);
console.log(this);
return '我是返回值';
}
const value = foo.myApply(obj, ['hello hahahahahaha', 'heiheihei']);
console.log(value);
C:\Users\Administrator\Desktop\手写\07_手写双向绑定vue2.js
C:\Users\Administrator\Desktop\手写\08_手写数据双向绑定vue3.js
let obj = {
name: '55',
};
proxyObj = new Proxy(obj, {
get: function (target, value) {
console.log('读取了数据');
return target[value];
},
set: function (target, value, newValue) {
target[value] = newValue;
console.log('设置了数据');
},
});
proxyObj.name;
proxyObj.name = 'alice';
C:\Users\Administrator\Desktop\手写\09_防抖.js
function deBounce(fn, delay) {
let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
}
C:\Users\Administrator\Desktop\手写\10_深拷贝.js
function isObject(value) {
const valueType = typeof value;
return value !== null && (valueType === 'function' || valueType === 'object');
}
function deepCopy(obj, map = new WeakMap()) {
const newObj = obj instanceof 'Array' ? [] : {};
if (!isObject(obj)) return obj;
if (map.has(obj)) return map.get(obj);
map.set(obj, newObj);
for (let key of obj) {
newObj[key] = deepCopy(obj[key], map);
}
}
C:\Users\Administrator\Desktop\手写\11_二叉树的遍历.js
/**
* 递归法前序遍历
*/
function dfsPreorderByRcs(tree) {
const output = [];
const visitLoop = (node) => {
if (node) {
// 先搜索出根节点的值,push进结果列表
output.push(node.data);
// 访问左子节点树,左子节点开始作为根节点进行下一轮递归
visitLoop(node.left);
// 同上述,递归遍历右子节点
visitLoop(node.right);
}
};
visitLoop(tree);
return output;
}
console.log('递归法DFS(前序): ', dfsPreorderByRcs(tree));
// 递归法DFS(前序): [ 1, 2, 4, 8, 9, 5, 10, 11, 3, 6, 12, 7 ]
C:\Users\Administrator\Desktop\手写\12_生成器模拟async和await.js
function requestData() {
return new Promise((resolve, reject) => {
resolve('11110000');
});
}
function* request() {
const data = yield requestData();
console.log('1__' + data);
const data2 = yield requestData();
console.log('2__' + data2);
return 'ending';
}
// const gen = request();
// const genData = gen.next();
// console.log(genData);
// genData.value.then((res) => {
// const genData2 = gen.next(res);
// console.log(genData2);
// genData2.value.then((res) => {
// const genData3 = gen.next(res);
// console.log(genData3);
// });
// });
function execGen(genFn) {
const gen = genFn();
const exec = (res) => {
let genData = gen.next(res);
if (genData.done) return genData.value;
genData.value.then((res) => {
exec(res);
});
};
exec();
}
execGen(request);