class MyIterator {
constructor(data) {
this.index = 0;
this.data = data;
}
next() {
if (this.hasNext()) {
return this.data[this.index++];
}
return null;
}
hasNext() {
return this.index < this.data.length;
}
}
const iterator = new MyIterator([1, 2, 3, 4, 5]);
while (iterator.hasNext()) {
console.log(iterator.next());
}
//单例模式
//一个构造函数只有一个实例
class mySingle {
constructor() {
if (!mySingle.instance) {
mySingle.instance = this;
}
return mySingle.instance;
}
}
const s1 = new mySingle();
const s2 = new mySingle();
console.log(s1 == s2);
const object = {
id: 1,
get() {
console.log(this.id);
},
set(value) {
this.id += value;
},
};
const personProxy = new Proxy(object, {
get(target, property) {
if (property === 'id') {
console.log('Getting id');
return target[property];
}
return Reflect.get(target, property);
},
set(target, property, value) {
if (property === 'id') {
console.log('Setting id');
target[property] = value;
return true; // 返回true表示设置操作成功
}
return Reflect.set(target, property, value);
},
});
personProxy.get();
personProxy.set(5);
setTimeout(() => {
personProxy.get();
}, 1000);
//flower proxy
const Target = function () {
this.request = function () {
console.log("代理送花");
};
};
// // 定义代理对象
// const Proxy = function(target) {
// this.target = target;
// this.request = function() {
// console.log("在请求之前执行一些操作");
// this.target.request();
// console.log("在请求之后执行一些操作");
// };
// };
// // 创建目标对象实例
// const target = new Target();
// // 创建代理对象实例,并将目标对象传递给代理对象
// const proxy = new Proxy(target);
// // 通过代理对象发起请求
// proxy.request();
var obj = {
val: 5,
}
function test(obj) {
obj.val = 10;
console.log(obj.val);
var obj = { val: 20 };
console.log(obj.val);
}
test(obj);
console.log(obj.val);
function test(obj) {
console.log(typeof obj);
function obj() { };
}
test({});
function args2Array(args) {
var arr = [];
for (var i = 0; i < args.length; i++) {
arr[i] = args[i];
}
}
function getGlobal() {
return (function () { return this; }())
}
Array.prototype.myCall = function () {
const thisArg = arguments[0];
const args = [...arguments].slice(1);
const invokeFunc = this;
const isSrict = (function () { return this === undefined }());
if (isStrict) {
if (typeof thisArg === "number") {
thisArg = new Number(thisArg);
} else if (typeof thisArg === 'string') {
thisArg = new String(thisAr);
} else if (typeof thisArg === 'boolean') {
thisArg = new Boolean(thisArg)
}
}
if (!thisArg) {
return invokeFunc(...args);
}
const uniqProp = Symbol();
thisArg[uniqProp] = invokeFunc;
return thisArg[uniqProp](...args);
}
Array.prototype.myApply = function (thisArg, args) {
const invokeFunc = this;
const isSrict = (function () { return this === undefined }())
if (isSrict) {
if (typeof thisArg === 'number') {
thisArg = new Number(thisArg);
} else if (typeof thisArg === 'string') {
thisArg = new String(thisArg);
} else if (typeof thisArg === 'boolean') {
thisArg = new Boolean(thisArg);
}
}
if (!thisArg) {
return invokeFunc(...args);
}
const uniqProp = Symbol();
this[uniqProp] = invokeFunc;
return thisArg[uniqProp](...args);
}
//手写mybind
Function.prototype.myBind = function () {
const thisArg = arguments[0];
const boundParams = [...arguments].slice(1);
const boundTargetFunc = this;
if (typeof boundTargetFunc !== 'function') {
throw new TypeError('the bound target function must be a function');
}
function fBound() {
const restParams = [...arguments];
const allParams = boundParams.concat(restParams);
return boundTargetFunc.apply(this instanceof fBound ? this : thisArg, allParams);
}
fBound.prototype = Object.create(boundTargetFunc.prototype);
return fBound;
}
// 定义一个示例函数
function greet(name) {
console.log(`Hello, ${name}!`);
}
// 使用myBind创建一个绑定函数
const boundGreet = greet.myBind(null, 'John');
// 调用绑定函数
boundGreet(); // 输出: Hello, John!
//手写实现new
function myNew(Constructor, ...args) {
const obj = Object.create(Constructor.prototype);
Constructor.call(obj, ...args);
return obj;
}
//use myNew
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
console.log(`hello,my name is ${this.name}`);
}
const mike = myNew(Person, 'mike');
mike.greet();
//手写实现instanceof
function myInstanceof(obj, ctor) {
if (typeof ctor !== 'function') {
throw new TypeError('the second paramater must be a function');
}
const rightProto = ctor.prototype;
let leftProto = Object.getPrototypeOf();
let isInstanceFlag = leftProto === rightProto;
while (!isInstanceFlag && leftProto) {
if (leftProto == rightProto) {
isInstanceFlag = true;
} else {
leftProto = Object.getPrototypeOf(leftProto);
}
}
return isInstanceFlag;
}
//手写 Promise.prototype.finally
//finally情况下,rejected优先
Promise.prototype.myFinally = function (onFinally) {
return this.then(value => {
return Promise.resolve(onFinally()).then(() => value);
}),
reason => {
return Promise.resolve(onFinally()).THEN(() => { throw reason });
}
}
//手写promise.all
// 这个主要是考察如何收集每㇐个 Promise 的状态变化,在最后㇐个 Promise 状态变化时,对外发出信号。
// ● 判断 iterable 是否空
// ● 判断 iterable 是否全部不是 Promise
// ● 遍历,如果某项是 Promise,利⽤ .then 获取结果,如果 fulfilled,将 value 存在 values 中,并⽤fulfillCount 计数;如果是 rejected,直接 reject
// reason。
// ● 如果某项不是 Promise,直接将值存起来,并计数。
// ● 等所有异步都 fulfilled,fulfillCount 必将是 iterable 的⻓度(在 onFulfilled 中判断 fulfillCount),此时可以 resolve values。
Promise.all = function (iterable) {
const tasks = Array.from(iterable);
if (tasks.length == 0) {
return Promise.resolve([]);
}
if (tasks.every(task => !(task instanceof Promise))) {
return Promise.resolve(tasks);
}
return new Promise((resolve, reject) => {
const values = new Array(tasks.length).fill(null);
const fulfillCount = 0;
tasks.forach((task, index, arr) => {
if (task instanceof Promise) {
task.then(value => {
fulfillCount++;
values[index] = value;
if (fulfillCount === arr.length) {
resolve(values);
}
}, reason => {
reject(reason);
})
} else {
fulfillCount++;
values[index] = task;
}
})
})
}
//手写防抖节流
// 原理:
// 防抖( debounce ):不管事件触发频率多⾼,㇐定在事件触发 n 秒后才执⾏,如果你在㇐个事件触发的 n 秒内⼜触发了这个事件,就以新的事件
// 的时间为准, n 秒后才执⾏,总之,触发完事件 n 秒内不再触发事件, n 秒后再执⾏。(频繁触发就执⾏最后㇐次)
// 应⽤场景:
// 1. 窗⼝⼤⼩变化,调整样式
// 2. 搜索框,输⼊后 1000 毫秒搜索
// 3. 表单验证,输⼊1000 毫秒后验证
// 4. 频繁点击按钮,使⽤防抖避免重复提交请求
// 防抖实现:
// ● debunce 实则是个包装函数,通过传⼊操作函数和时间间隔,来返回㇐个新函数
// ● 新函数中主要是通过定时器来设置函数调⽤的频率
// ● flag 只有第㇐次触发的时候会⽴即执⾏
function debounce(handler, ms, flag) {
let timer = null;
return function (...args) {
clearTimeout(timer);
if (flag && timer) {
handler.apply(this, args);
}
timer = setTimeout(() => {
handler.apply(this, args);
}, ms)
}
}
//demo
window.addEventListener('resize', debounce(handler, 1000));
function handler() {
console.log('ok');
}
// 节流
// 原理:
// 节流( throttle ):不管事件触发频率多⾼,只在单位时间内执⾏㇐次。(频繁触发,还是按照时间间隔执⾏)
// 应⽤场景:
// 1. ⿏标不断点击触发,mousedown(单位时间内只触发㇐次)
// 2. 监听滚动事件,⽐如是否滑到底部⾃动加载更多,⽤throttle 来判断
// 节流实现
// ● 和防抖不同的是,防抖中是取消定时器,节流中是定时器到时间⾃动执⾏,仅仅是将 timer 变量设置为 null
// ● 时间戳版:第㇐次执⾏,最后㇐次不执⾏
//定时器版,第一次不执行,最后一次执行
//时间戳版
function throlttle(handler, ms) {
let pre = 0;
return function (...args) {
if (Date.noew() - pre > ms) {
pre = Date.now();
handler.apply(this, args);
}
}
}
//定时器版
function throttle(handler, ms) {
let timer = null;
return function (...args) {
if (!timer) {
timer = setTimeout(() => {
timer = null;
handler.apply(this, args);
}, ms)
}
}
}
//手写深拷贝,考虑多种数据类型的处理
function deepClone(val) {
const type = getType(val);
if (type === "object") {
const result = {};
Object.keys(val).forEach(key => {
result[key] = deepClone(val[key]);
})
} else if (type === 'array') {
return val.map(item => deepClone(item));
} else if (type === "date") {
return new Date(val.getTime());
} else if (type === "regexp") {
return new RegExp(val.source, val.flags);
} else if (type === "function") {
return eval("(" + val.toString() + ")");
} else if (type === "map" || type === "set") {
return new val.constructor(val);
} else {
return val;
}
}
//实现柯里化
//按定义实现
function curry(fn, presetParam) {
return function () {
return fn.apply(this, [preseParam, ...arguments])
}
}
//扩展多参数
function curry1(fn, ...args) {
return function () {
return fn.apply(this, [...args, ...arguments]);
}
}
//定长柯里化,执行时机判断
function curry2(fn, ...args) {
const len = fn.length;
return function () {
const allArgs = [...args, ...arguments];
if (allArgs.length >= len) {
return fn.apply(this, allArgs);
} else {
return curry2.call(null, fn.bind(this), ...args)
}
}
}
//虽然发布订阅out,但是还是记录一下
class Listener {
constructor(id, eventName, callback) {
this.id = id;
this.eventName = eventName;
this.callback = callback;
}
}
class EventBus {
constructor() {
this.events = {};
this.autoIncreaseId = 1;
}
addListener(listener) {
if (this.evnents[listener.eventName]) {
this.events[listener.eventName].push(listener);
} else {
this.events[listener.eventName] = [listener];
}
return listener;
}
on(eventName, handler) {
const listener = new Listener(this.autoIncreaseId++, eventName, handler);
return this.addListener(listener);
}
emit(eventName,handler){
if(this.events[eventName]){
this.events[eventName].forEach(({callback})=>{
callback(...args);
})
}
}
off(eventName,listener){
const listeners=this.events[eventName];
if(listeners){
const index=listeners.findIndex(l=>l.id===listener.id);
if(index!==-1){
listeners.splice(index,1)
}
}
}
remove(eventName){
if(this.events[eventName]){
delete this.events[evenName];
}
}
once(eventName,handler){
const that=this;
const id=this.autoIncreaseId++;
const onceCallback=function(){
handler(...arguments);
const index=that.events[eventName].findIndex(l=>l.id===id);
that.events[eventName].splice(index,1)
}
const listener=new Listener(id,eventName,onceCallback);
return this.addListener(listener);
}
}
console