1: Array方法
Array.prototype.forEach
接受两个参数callback, this(ctx)
Array.prototype.myForEach = function (callBack) {
var content = arguments[1] || window;
var _arr = this;
var len = _arr.length;
for (var i = 0 ; i < len; i++) {
callBack.apply(content, [_arr[i], i, _arr]);
}
}
Array.prototype.map
Array.prototype.myMap = function (callBack) {
var content = arguments[1] || window;
var _arr = this;
var _len = _arr.length;
var _newArr = [];
for (var i = 0 ; i < _len; i++) {
_newArr.push(callBack.apply(content, [_arr[i], i, _arr]));
}
return _newArr;
}
备注: 这里简单的实现一下,其实是需要深拷贝一下每一项的结果。
Array.prototype.filter
Array.prototype.myFilter = function (callBack) {
var _arr = this;
var args = arguments[1] || window;
var _len = _arr.length;
var newArr = [];
for (var i = 0 ; i < _len; i++) {
if (callBack.apply(args, [_arr[i], i, _arr])) {
newArr.push(_arr[i])
}
}
return newArr;
}
Array.prototype.every
Array.prototype.myEvery = function (callBack) {
var _arr = this;
var args = arguments[1] || window;
var _len = _arr.length;
var result = true;
for (var i = 0 ; i < _len ; i++) {
if (!callBack.apply(args, [_arr[i], i, _arr])) {
result = false;
break;
}
}
return result;
}
Array.prototype.some
Array.prototype.mySome = function (callBack) {
var _arr = this;
var args = arguments[1] || window;
var _len = _arr.length;
var result = false;
for (var i = 0 ; i < _len ; i++) {
if (callBack.apply(args, [_arr[i], i, _arr])) {
result = true;
break;
}
}
return result;
}
Array.prototype.reduce
Array.prototype.myReduce = function (callBack, initialvalue) {
var _arr = this;
var _len = _arr.length;
for (var i = 0; i < _len; i++) {
initialvalue = callBack(initialvalue, _arr[i], i, _arr);
}
return initialvalue;
}
数组扁平化
- reduce + ...
Array.prototype.flatArray1 = function (arr) {
if (!arr.length) return;
return arr.reduce((prev, item) => {
Array.isArray(item) ? [...prev, ...flatArray1(item)] : [...prev, item]
}, [])
}
- reduce + concat
Array.prototype.flatArray2 = function (arr) {
if (!arr.length) return;
return arr.reduce((prev, item) => {
prev.concat(Array.isArray(item) ? flatArray2(item) : item)
}, [])
}
数组去重
- reduce + includes
function unique (arr) {
if (!arr.length) return;
let newArr = [];
return arr.reduce((prev, item) => {
return newArr.includes(item) ? newArr: newArr.push(item);
}, 0)
}
- forEach + indexOf
function unique2(arr) {
let newArr = [];
arr.forEach(item => {
newArr.indexOf(item) === -1 ? newArr.push(item) : newArr;
})
}
- new Set + ...
function unique3(arr) {
return [...new Set(arr)];
}
- new Set + Array.from
function unique4(arr) {
return Array.from(new Set(arr));
}
- 利用对象键的唯一性
function unique5(arr) {
let newArr = [];
let obj = {};
for (let i = 0 ; i < arr.length ; i++) {
if (!obj[arr[i]]) {
newArr.push(arr[i]);
obj[arr[i]] = 1;
}
else {
obj[arr[i]]++;
}
}
return newArr;
}
2: Function
Function.prototype.call
Function.prototype.myCall = function (ctx) {
var args = [...arguments].slice(1);
ctx = ctx || window;
var name = Symbol();
ctx[name] = this;
var result = ctx[name](...args);
delete ctx[name];
return result;
}
Function.prototype.apply
Function.prototype.myApply = function (ctx, array) {
ctx = ctx || window;
var name = Symbol();
ctx[name] = this;
var result = ctx[name](...array);
delete ctx[name];
return result;
}
Function.prototype.bind
Function.prototype.myBind = function (ctx) {
ctx = ctx || window;
var args = [...arguments].slice(1);
var func = this;
var FNOP = {};
var returnFunc = function () {
var newArgs = [...args, ...arguments];
return func.apply(this instanceof returnFunc ? this : ctx, ...newArgs);
}
FNOP.prototype = func.prototype;
returnFunc.prototype = new fNOP();
return returnFunc;
}
实现 add(1)(2)(3) = add(1, 2, 3) = add(1,2)(3) = 6
使用currying函数,return一个新函数
const sum = (a, b, c) => a + b + c;
function currying(fn, args) {
var len = fn.length;
args = args || [];
return function () {
var newArgs = [...args, ...arguments];
if (newArgs.length < len) {
return currying(fn, newArgs);
}
else {
return fn.call(this, ...newArgs);
}
}
}
实现 add(1)(2)(3)() = add(1, 2, 3)() = add(1,2)(3)() = 6
同上
const sum = (a, b, c) => a + b + c;
function currying(fn, args) {
var len = fn.length;
args = args || [];
return function () {
var newArgs = [...args, ...arguments];
if (newArgs.length < len) {
return currying.call(this, fn, newArgs);
}
else {
return fn.bind(this, ...newArgs);
}
}
}
实现一个add函数
题目描述:
实现一个add函数:
add(1)(2)(3)() = 6
add(1)(2)(3, 4)() = 10
function add() {
var now_args = [...arguments];
var fn = function () {
var args2 = [...arguments];
if (args2.length) return fn.toString();
now_args = [...now_args, ...args2];
return fn;
}
fn.toString = function () {
return now_args.reduce((prev, next) => prev + next)
}
return fn;
}
3. Promise
实现一个简单的Promise
let p1 = new MyPromise((resolve, reject) => {
resolve(1);
});
p1.then(data => console.log(data))
class MyPromise {
constructor(executor) {
this.initValue();
this.initResolve();
this.initReject();
try {
executor(this.resolve, this.reject);
}
catch (e) {
this.reject(e);
}
}
initValue() {
this.promiseState = 'pending';
this.promiseResult = null;
this.onFulfilledCallBacks = [];
this.onRejectedCallBacks = [];
}
initResolve() {
this.resolve = this.resolve.bind(this);
}
initReject() {
this.reject = this.reject.bind(this);
}
resolve(value) {
if (this.promiseState != 'pending') return;
this.promiseState = 'fulfilled';
this.promiseResult = value;
this.onFulfilledCallBacks.forEach(fn => fn());
}
reject(reason) {
if (this.promiseState != 'pending') return;
this.promiseState = 'rejected';
this.promiseResult = reason;
this.onRejectedCallBacks.forEach(fn => fn());
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
var thenPromise = new MyPromise((resolve, reject) => {
var rp = (cb) => {
// 这里的cb就是回调onFulfilled or 回调onRejected
try {
var x = cb(this.promiseResult);
if (x === thenPromise) return; // 不能返回自身
if (x instanceof MyPromise) {
x.then(resolve, reject); // 如果是promise 抛出结果
}
else {
resolve(x); // 普通值,走resolve
}
}
catch (e) {
reject(e);
}
}
if (this.promiseState === 'pending') {
// 在pending状态下: 分别存入fulfilled和rejected对应的数组
// 主要是为了处理executor中是异步的情况
this.onFulfilledCallBacks.push(() => {rp(onFulfilled)});
this.onRejectedCallBacks.push(() => {rp(onRejected)});
}
if (this.promiseState === 'fulfilled') {
// 执行onFulfilled
rp(onFulfilled);
}
if (this.promiseState === 'rejected') {
// 执行onRejected
rp(onRejected);
}
})
return thenPromise;
}
}
实现Promise.race
static race(promiseArray) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promiseArray)) {
reject('no array');
}
promiseArray.forEach(promise => {
if (promise instanceof MyPromise) {
promise.then(data => {
resolve(data);
}, err => {
reject(err);
})
}
else {
resolve(promise);
}
})
})
}
实现Promise.all
static all(promiseArray) {
const result = [];
const count = 0;
return new Promise((resolve, reject) => {
const addPromsie = (promise, index) => {
result[index] = promise;
count++;
if (count === promiseArray.length) resolve(result);
}
promiseArray.forEach((promise, index) => {
if (promise instanceof MyPromise) {
promise.then(data => addPromsie(data, index), err => reject(err));
}
else {
addPromsie(promise, index);
}
})
})
}
4: Object
1: Object.entries
Object.prototype.my_entries = function (obj) {
if (obj === null || obj === undefined) {
throw new Error('Cannot convert undefined or null to object');
}
let new_arr = [];
for (let key in obj) {
obj.hasOwnProperty(key) && new_arr.push([key, obj[key]]);
}
return new_arr;
}
测试用例:
let example1 = null;
let example2 = ['a', 'b', 'c'];
let example3 = { name: 'yhq', age: 24 };
Object.my_entries(example1);
Object.my_entries(example2);
Object.my_entries(example3);
2: Object.values
Object.prototype.my_values = function (obj) {
if (obj === null || obj === undefined) {
throw new Error('Cannot convert undefined or null to object');
}
let new_arr = [];
for (let key in obj) {
obj.hasOwnProperty(key) && new_arr.push(obj[key]);
}
return new_arr;
}
测试用例
let example1 = null;
let example2 = ['a', 'b', 'c'];
let example3 = { name: 'yhq', age: 24 };
Object.my_values(example1);
Object.my_values(example2);
Object.my_values(example3);
3. Object.keys
Object.prototype.my_keys = function (obj) {
if (obj === null || obj === undefined) {
throw new Error('Cannot convert undefined or null to object');
}
let new_arr = [];
for (let key in obj) {
obj.hasOwnProperty(key) && new_arr.push(key);
}
return new_arr;
}
测试用例
let example1 = null;
let example2 = ['a', 'b', 'c'];
let example3 = { name: 'yhq', age: 24 };
Object.my_keys(example1);
Object.my_keys(example2);
Object.my_keys(example3);
5: 数据结构
1: 链表 --> singleList
简单的介绍一下js中的链表结构,跟正常的C和C++里面是不一样的。
const singleList = {
data: 1,
next: {
data: 2,
next: {
data: 3,
next: {
data: 4,
next: null
}
}
}
}
- 链表的创建,增加, 删除,修改
// 生成链表节点
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
class SingleLinkList {
constructor() {
this.head = null;
this.length = 0;
}
// 添加
add(data) {
let node = new Node(data);
if (this.head === null) {
this.head = node;
}
else {
let current = this.head;
while (current.next) {
current = current.next;
}
current.next = node;
}
this.length++;
}
// 获取
get(data) {
let current = this.head;
while (current) {
if (current.data === data) {
return current;
}
current = current.next;
}
}
// 插入
insert(data, target) {
let node = new Node(data);
let current = this.head;
while(current.next) {
if (current.data === target) {
node.next = current.next;
current.next = node;
this.length++;
break;
}
current = current.next;
}
}
// 删除
remove(data) {
let current = this.head;
let prev = null;
while (current) {
if (current.data === data) {
if (prev === null) {
// 删除的是头节点
this.head = current.next;
}
else {
prev.next = current.next;
}
return true;
}
prev = current;
current = current.next;
}
}
}
- 链表是否为环链表
function hasCycle(linkList) {
let headNode = linkList.head;
let slower = headNode;
let faster = headNode;
while(slower.next) {
if (!faster.next || !faster.next.next) {
return false;
}
if (faster === slower) {
retunr true;
}
slower = slower.next;
faster = faster.next.next;
}
}
6: 其他
1: 常见的js优化
- 防抖
function deboundce(fn, delay) {
var timer = null;
return function () {
if (timer) clearTimeout(timer);
var args = [...arguments];
var self = this;
timer = setTimeout(() => {
fn.apply(self, ...args);
}, delay);
}
}
- 节流
function throttle(fn, delay) {
var tag = true;
return function () {
if (!tag) return;
tag = false;
var args = [...arguments];
var self = this;
setTimeout(() => {
fn.apply(self, ...args);
tag = true;
}, delay)
}
}
- 响应的超时处理
题目描述:
如何控制一个接口请求,在给定时间time内可以响应走成功,否则抛出异常
测试: time = 3s, 接口返回时间是4s, 走错误。
测试: time = 3s, 接口返回时间是2s, 走成功。
function getIterator(timer) {
return new Promise((resolve, reject) => {
setTimeout(() => {
// 用setTimeout模拟一下接口请求
resolve('get data')
}, timer)
})
}
function sleep(delay) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('error');
}, delay)
})
}
function timeOut(sleep, delay) {
return new Promise.all([getIterator(4), sleep(delay)]);
}