如果你有梦想,一定要来大城市,这里可以帮您实现你想要的
有些梦想,需要借助城市的力量才能实现
文章会持续更新
1.手写防抖(debounce)和 节流(throttle)
function debounce(f, wait) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => {
f(...args);
}, wait);
}
}
function throttle(f, wait) {
let timer;
return (...args) => {
if (timer) { return };
timer = setTimeout(() => {
fn(...args);
timer = null;
}, wait);
}
}
2.手动实现一下instanceof的功能
核心: 原型链的向上查找。
function myInstanceOf(left, right) {
// 基本数据类型直接返回false
if (typeof left !== 'object' || left === null) return false;
// getPrototypeOf是Object对象自带的一个方法,能够拿到参数的原型对象
let pro = Object.getPrototypeOf(left);
while(true) {
//查找到尽头,还没找到
if (pro === null) return false;
//找到相同的原型对象
if (pro === right.prototype) return true;
pro = Object.getPrototypeOf(pro);
}
}
3. Object.is和===的区别?
Object在严格等于的基础上修复了一些特殊情况下的失误,具体来说就是+0和-0,NaN和NaN。 源码如下:
function is(x, y) {
if (x === y) {
//运行到1/x === 1/y的时候x和y都为0,但是1/+0 = +Infinity, 1/-0 = -Infinity, 是不一样的
return x !== 0 || y !== 0 || 1/x === 1/y;
} else {
//NaN===NaN是false,这是不对的,我们在这里做一个拦截,x !== x,那么一定是 NaN, y 同理
//两个都是NaN的时候返回true
return x !== x && y !== y
}
}
4.最优的组合继承----寄生组合继承
function Parent() {
this.name = 'parent';
this.play = [1,2,3];
}
function Child() {
Parent.call(this);
this.type = 'child';
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
5.模拟实现map函数
Array.prototype.map = function(callbackFn, thisArg) {
// 处理数组类型异常
if (this === null || this === undefined) {
throw new TypeError("Cannot read property 'map' of null or undefined");
}
// 处理回调类型异常
if (Object.prototype.toString.call(callbackFn) != '[object Function]') {
throw new TypeError(callbackfn + ' is not a function');
}
// 草案中提到要先转换为对象
let O = Object(this);
let T = thisArg;
let len = O.length >>> 0;
let A = new Array(len);
for(let k=0; k < len; k++) {
// 还记得原型链那一节提到的 in 吗?in 表示在原型链查找
// 如果用 hasOwnProperty 是有问题的,它只能找私有属性
// 需要注意的就是使用 in 来进行原型链查找。同时,如果没有找到就不处理,能有效处理稀疏数组的情况。考虑类似于[ , , , ,1, , , , , , 2, , , , , 3, , , , , 4] 的稀疏数组性能
if (k in O) {
let kValue = O[k];
// 依次传入this, 当前项,当前索引,整个数组
let mappedValue = callbackFn.call(T, kValue, k, O);
A[k] = mappedValue;
}
}
return A;
}
6.模拟实现reduce函数
Array.prototype.reduce = function(callbackFn, initialValue) {
if (this === null || this === undefined) {
throw new TypeError("Cannot read property 'reduce' of null or undefined");
}
if (Object.prototype.toString.call(callbackFn) != '[object Function]') {
throw new TypeError(callbackfn + ' is not a function')
}
let O = Object(this);
let len = O.length >>> 0;
let k = 0;
let accumulator = initialValue;
if (accumulator === undefined) {
for (; k<len; k++) {
if (k in O) {
accumulator = O[k];
k++;
break;
}
}
}
if (k === len && accumulator === undefined)
throw new Error('Each element of the array is empty');
for(;k<len;k++) {
if (k in O) {
accumulator = callbackFn.call(undefined, accumulator. O[k], k, O);
}
}
return accumulator;
}
7.实现 push , pop 方法
Array.prototype.push = function(...items) {
let O = Object(this);
let len = this.length >>> 0;
let argCount = items.length >>> 0;
if (len + argCount > 2 ** 53 - 1) {
throw new TypeError("The number of array is over the max value restricted!")
}
for (let i = 0; i<argCount; i++) {
O[len+1] = items[i];
}
let newLength = len + argCount;
O.length = newLength;
return newLength;
}
Array.prototype.pop = function() {
let O = Object(this);
let len = this.length >>> 0;
if (len === 0) {
O.length = 0;
return undefined;
}
len --;
let value = O[len];
delete O[len];
O.length = len;
return value;
}
8.实现filter方法
Array.prototype.filter = function(callbackfn, thisArg) {
// 处理数组类型异常
if (this === null || this === undefined) {
throw new TypeError("Cannot read property 'filter' of null or undefined");
}
// 处理回调类型异常
if (Object.prototype.toString.call(callbackfn) != "[object Function]") {
throw new TypeError(callbackfn + ' is not a function')
}
let O = Object(this);
let len = O.length >>> 0;
let resLen = 0;
let res = [];
for(let i = 0; i < len; i++) {
if (i in O) {
let element = O[i];
if (callbackfn.call(thisArg, O[i], i, O)) {
res[resLen++] = element;
}
}
}
return res;
}
9.模拟实现一个new的效果
function newOperator(ctor, ...args) {
if (typeof ctor !== 'function') {
throw 'newOperator function the first param must be a function';
}
let obj = Object.create(ctor.prototype);
let res = ctor.call(obj, args);
let isObject = typeOf res === 'object' && res !== null;
let isFunction = typeof res === 'function';
return isObject || isFunction ? res : obj;
}
10.模拟实现一个bind的效果
Function.prototype.bind = function(content, ...args) {
// 异常处理
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this;
var fbound = function() {
self.apply(this instanceof self ?
this : content, args.concat(Array.prototype.slice.call(arguments)));
}
fbound.prototype = Object.create(self.prototype);
return fbound;
}
11. 实现一个 call/apply 函数
Function.prototype.call = function (context, ...args) {
let context = context || window;
let fn = Symbol('fn');
context.fn = this;
let result = context.fn(...args);
delete context.fn;
return result;
}
Function.prototype.apply = function (context, args) {
let context = context || window;
let fn = Symbol('fn');
context.fn = this;
let result = context.fn(...args);
delete context.fn;
return result;
}
12.手动实现浅拷贝
const shallowClone = (target) => {
if (typeof target === 'object' && target !== null) {
const cloneTarget = Array.isArray(target) ? [] : {};
for (let prop in target) {
if (target.hasOwnProperty(prop)) {
cloneTarget[prop] = target[prop];
}
}
return cloneTarget;
} else {
return target;
}
}
13.手动实现深拷贝
const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null)
const deepClone = function (obj, hash = new WeakMap()) {
if (obj.constructor === Date)
return new Date(obj) // 日期对象直接返回一个新的日期对象
if (obj.constructor === RegExp)
return new RegExp(obj) //正则对象直接返回一个新的正则对象
//如果循环引用了就用 weakMap 来解决
if (hash.has(obj)) return hash.get(obj)
let allDesc = Object.getOwnPropertyDescriptors(obj)
//遍历传入参数所有键的特性
let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)
//继承原型链
hash.set(obj, cloneObj)
for (let key of Reflect.ownKeys(obj)) {
cloneObj[key] = (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') ? deepClone(obj[key], hash) : obj[key]
}
return cloneObj
}
14.实现node 中回调函数的机制
function EventEmitter() {
this.events = new Map();
}
const wrapCallback = (fn, once = false) => ({
callback: fn,
once
})
EventEmitter.prototype.addListener = function(type, fn, once = false) {
let handler = this.events.get(type);
if (!handler) {
this.events.set(type, wrapCallback(fn, once));
} else if (handler && typeof handler.callback === 'function') {
this.events.set(type, [handler, wrapCallback(fn, once)]);
} else {
handler.push(wrapCallback(fn, once));
}
}
EventEmitter.prototype.removeListener = function(type, listener) {
let handler = this.events.get(type);
if (!handler) return;
if (!Array.isArray(handler)) {
if (handler.callback === listener.callback) this.events.delete(type);
else return;
}
for (let i=0; i<handler.length; i++) {
let item = handler[i];
if (item.callback === listener.callback) {
handler.splice(i, 1);
i--;
if (handler.length === 1) {
this.events.set(type, handlerp[0])
}
}
}
}
EventEmitter.prototype.once = function(type, fn) {
this.addListener(type, fn, true);
}
EventEmitter.prototype.emit = function(type, ...args) {
let handler = this.events.get(type);
if (!handler) return;
if (Array.isArray(handler)) {
handler.map((item) => {
item.callback.apply(this, args);
if (item.once) {
this.removeListener(type, item)
}
})
} else {
handler.callback.apply(this, args);
this.removeListener(type, handler)
}
return true;
}
EventEmitter.prototype.removeAllListener = function(type) {
let handler = this.events.get(type);
if (!handler) return;
else this.events.delete(type);
}
15.手写promise
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
function MyPromise(executor) {
let self = this;
self.value = null;
self.error = null;
self.status = PENDING;
self.onFulfilledCallbacks = [];
self.onRejectedCallbacks = [];
const resolve = (value) => {
if (self.status !== PENDING) return;
setTimeout(() => {
self.status = FULFILLED;
self.value = value;
self.onFulfilledCallbacks.forEach((callback) => callback(self.value))
})
}
const reject = (error) => {
if (self.status !== PENDING) return;
setTimeout(() => {
self.status = REJECTED;
self.error = error;
self.onRejectedCallbacks.forEach((callback) => callback(self.error)
})
}
executor(resolve, reject);
}
MyPromise.prototype.then = function(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => {throw error};
let bridgePromise;
let self = this;
if (this.status === PENDING) {
return bridgePromise = new MyPromise((resolve,reject) => {
self.onFulfilledCallbacks.push((value) => {
try {
let x = onFulfilled(value);
resolvePromise(bridgePromise, x, resolve, reject);
} catch (e) {
reject(e);
}
});
self.onRejectedCallbacks.push((error) => {
try {
let x = onRejected(error);
resolvePromise(bridgePromise, x, resolve, reject);
} catch (e) {
reject(e);
}
})
})
} else if (this.status === FULFILLED) {
return bridgePromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
try {
let x = onFulfilled(self.value);
resolvePromise(bridgePromise, x, resolve, reject);
} catch (e) {
reject(e);
}
})
})
} else {
return bridgePromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(self.error);
resolvePromise(bridgePromise, x, resolve, reject);
} catch (e) {
reject(e);
}
})
});
}
}
function resolvePromise(bridgePromise, x, resolve, reject) {
if (x instanceof MyPromise) {
if (x.status === PENDING) {
x.then(y => {
resolvePromise(bridgePromise, y, resolve,reject);
}, error => {
reject(error);
})
} else {
x.then(resolve, reject)
}
} else {
resolve(x);
}
}
MyPromise.prototype.catch = function(onRejected) {
return this.then(null, onRejected);
}
MyPromise.resolve = (param) => {
if (param instanceof MyPromise) return param;
return new MyPromise((resolve, reject) => {
if (param && param.then && param.then === 'function') {
param.then(resolve, reject);
} else {
resolve(param);
}
})
}
MyPromise.reject = (reason) => {
return new Promise((resolve, reject) => {
reject(reason);
})
}
MyPromise.prototype.finally = function(callback) {
this.then(value => {
return MyPromise.resolve(callback()).then(() => {
return value;
})
}, error => {
return MyPromise.reject(callback()).then(() =>{
throw error;
})
})
}
MyPromise.all = function(promises) {
return new Promise((resolve, reject) => {
let result = [];
let index = 0;
let len = promises.length;
if (len === 0) {
resolve(result);
return;
}
for(let i=0; i< len; i++) {
MyPromise.resolve(promises[i]).then(data => {
result[i] = data;
index++;
if (index === len) resolve(result);
}).catch(err => {
reject(err);
})
}
})
}
MyPromise.race = function(promises) {
return new MyPromise((resolve, reject) => {
let len = promises.length;
if (len === 0) {
return;
}
for(let i=0; i< len; i++) {
MyPromise.resolve(promises[i]).then(data => {
resolve(data);
return;
}).catch(err => {
reject(err);
return;
})
}
})
}
16.链表反转
class reverseList = function(head) {
let pre = null;
let cur = head;
while(cur !== null) {
let next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
17.Promise实现多图 预加载
function preLoadImage(source){
let pr = [];
source.foeEach(url => {
let p = loadImage(url)
})
Promise.all(pr)
.then((images) => {
console.log(images)
})
}
function loadImage(url) {
return new Promise((resolve, reject) => {
let img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = url;
})
}
18.完成函数computed、multiply, add满足一下功能
-
- computed(multipy(num2), add(num3))(num1) // 等于 num1 - num2 + num3
-
- computed(add(num2), multiply(num3), add(num4))(num1) // 等于 num1 + num2 - num3 + num4
const num1 = 1
const num2 = 2
const num3 = 3
const num4 = 4
let result = 0
function computed(...params) {
if (!params) return
function fn(value) {
result = value
params.forEach(item => {
// console.log('item', item)
// console.log('result', result)
result += item
})
// console.log('result2', result)
return result
}
return fn
}
function add(value) {
return value
}
function multiply(value) {
return -value
}
console.log(computed(add(num2),multiply(num3),add(num4))(num1)) // 1 + 2 - 3 + 4
19.css3绘制扇形
<div class="shanxing">
<div class="sx1"></div>
<div class="sx2"></div>
</div>
.shanxing{
position: relative;
width: 200px;
height: 200px;
border-radius: 100px;
background-color: yellow;
}
.sx1{
position: absolute;
width: 200px;
height: 200px;
transform: rotate(45deg);
clip: rect(0,100px,200px,0);
border-radius: 100px;
background-color: #fff;
}
.sx2{
position: absolute;
width: 200px;
height: 200px;
transform: rotate(-45deg);
clip: rect(0,100px,200px,0);
border-radius: 100px;
background-color: #fff;
}