Flattened Array function flatten(value) {
if (typeof(value) !== 'object' || value == null){
return value;
}
if(Array.isArray(value)){
return flattenArray(value);
}
return flattenObj(value);
}
function flattenArray(array) {
return array.reduce((acc, curr) => acc.concat(flatten(curr)),[]);
}
function flattenObj(object){
const flattenedObj = {}
for (const [key, value] of Object.entries(object)){
const valueIsObj = typeof value == 'object' && value !== null && !Array.isArray(value);
const flattenedValue = flatten(value);
if(valueIsObj){
Object.assign(flattenedObj, flattenedValue);
}
else{
flattenedObj[key] = flattenedValue;
}
}
return flattenedObj;
}
exports.flatten = flatten;
Testing Framework function describe(testSuiteName, func) {
console.log(`beginning test suite ${testSuiteName}`);
try {
func();
console.log(`successfully completed test suite ${testSuiteName}`);
} catch (error) {
const { testCaseName, errorMessage } = error;
console.error(
`failed running test suite ${testSuiteName} on ` +
`test case ${testCaseName} with error message ${errorMessage}`
);
}
}
function it(testCaseName, func) {
console.log(`beginning test case ${testCaseName}`);
try {
func();
console.log(`successfully completed test case ${testCaseName}`);
} catch (errorMessage) {
throw { testCaseName, errorMessage };
}
}
function expect(actual) {
return new ExpectFunctions(actual);
}
class ExpectFunctions {
constructor(actual) {
this.actual = actual;
this.stringifiedActual = JSON.stringify(actual);
}
toExist() {
if (this.actual == null) {
throw `expected value to exist but got ${this.stringifiedActual}`;
}
}
toBe(expected) {
if (this.actual !== expected) {
throw `expected ${this.stringifiedActual} to be ${JSON.stringify(
expected
)}`;
}
}
toBeType(type) {
if (typeof this.actual !== type) {
throw `expected ${
this.stringifiedActual
} to be of type ${type} but got ${typeof this.actual}`;
}
}
}
// Do not edit the lines below.
exports.describe = describe;
exports.it = it;
exports.expect = expect;
Array Methods Array.prototype.myMap = function (callback) {
const output = [];
for(let i=0; i < this.length; i++){
output.push(callback(this[i], i, this));
}
return output;
};
Array.prototype.myFilter = function (callback) {
const output = [];
for(let i=0;i<this.length;i++){
if(callback(this[i], i, this) === true){
output.push(this[i])
}
}
return output;
};
Array.prototype.myReduce = function (callback, initialValue) {
let accumulator = initialValue;
for(let i=0;i<this.length;i++){
if(i === 0 && initialValue === undefined){
accumulator = this[i];
}
else{
accumulator = callback(accumulator, this[i], i, this);
}
}
return accumulator;
};
Event Target class EventTarget {
constructor(){
this.listeners = {}
}
addEventListener(name, callback) {
if(!this.listeners.hasOwnProperty(name)){
this.listeners[name] = new Set();
}
this.listeners[name].add(callback);
}
removeEventListener(name, callback) {
this.listeners[name]?.delete(callback);
}
dispatchEvent(name) {
this.listeners[name]?.forEach(callback => {
callback();
})
}
}
exports.EventTarget = EventTarget;
function debounce(callback, delay, immediate = false) {
let timerId;
return function(...args){
clearTimeout(timerId);
let shouldCallImmediately = timerId == null && immediate;
if(shouldCallImmediately){
callback.apply(this, args)
}
timerId = setTimeout(() => {
if(!immediate){
callback.apply(this, args);
}
timerId = null;
}, delay)
}
}
exports.debounce = debounce;
Debounce