★★★手写代码:实现forEach map filter reduce
Array.prototype._forEach = function (fn, thisArg) {
if (typeof fn !== 'function') throw '参数必须为函数'
if (!Array.isArray(this)) throw '只能对数组使用此方法'
let arr = this
for (let i = 0; i < arr.length; i++) {
fn.call(thisArg, arr[i], i, arr)
}
}
Array.prototype._map = function (fn, thisArg) {
if (typeof fn !== 'function') throw "参数必须是回调函数"
if (!Array.isArray(this)) throw "只能为数组使用此方法"
const arr = this
const newArr = []
for (let i = 0, len = arr.length; i < len; i++) {
newArr.push(fn.call(thisArg, arr[i], i, arr))
}
return newArr
}
Array.prototype._filter = function (fn, thisArg) {
if (typeof fn !== 'function') throw "参数必须是回调函数"
if (!Array.isArray(this)) throw "只能为数组使用此方法"
const arr = this
const newArr = []
for (let i = 0, len = arr.length; i < len; i++) {
if (fn.call(thisArg, arr[i], i, arr)) {
newArr.push(arr[i])
}
}
return newArr
}
Array.prototype._reduce = function (_reducer, initialValue) {
if (typeof _reducer !== 'function') throw "参数必须是回调函数"
if (!Array.isArray(this)) throw "只能为数组使用此方法"
if ((!this.length && !initialValue)) throw "请传入初始值或者给非空对象使用此方法"
let arr = this
let result = initialValue || arr[0]
for (let i = 0, len = arr.length; i < len; i++) {
if (!initialValue && i == 0) continue
result = _reducer(result, arr[i], i, this)
}
return result
}
★★★ 手写实现一个简易的 Vue Reactive
★★★ 手写代码,监测数组变化,并返回数组长度
const ArrayProto = []
Object.getOwnPropertyNames(Array.prototype).forEach(method => {
if (typeof Array.prototype[method] === "function") {
ArrayProto[method] = function () {
console.log("我已经监听到数组触发了" + method + "事件")
let len = this.length
let result = Array.prototype[method].apply(this, arguments)
console.log(len, this.length);
if (len !== this.length) return this.length
return result
}
}
})
let list = [1, 2, 3]
list.__proto__ = ArrayProto
console.log(list.push(2), list.pop(2), list.slice(2), list.unshift(2));
★★★ 手写原生继承,并说出局限性?
★★★★ 手写一个柯里化函数
function Curry(fn,...args){
return (..._args)=>{
return fn(...args,..._args))
}
}
function V(l,w,h){
return l*w*h
}
const hcy =Curry(V,10)
hcy(5,8)
hcy(6,7)
★★★ 手写一个反柯里化函数
Function.prototype.unCurrying = function() {
const self = this
return function(...rest) {
return Function.prototype.call.apply(self, rest)
}
}
★★★★ 手写一个Promise
class Promise{
constructor(executor){
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
try{
executor(this.resolve, this.reject);
} catch (err) {
reject(err);
}
}
resolv(value){
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
}
};
reject(reason) {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
}
};
then(onFulfilled,onRejected) {
let promise2 = new Promise((resolve, reject)=>{
if (this.state === 'fulfilled') {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
};
if (this.state === 'rejected') {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
};
if (this.state === 'pending') {
this.onResolvedCallbacks.push(()=>{
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
})
this.onRejectedCallbacks.push(()=>{
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
})
}
});
return promise2;
}
}
★★★ 手写一个instanceOf
function instanceOf(left,right){
let proto = left.__proto__
let prototype = right.prototype
while(true){
if(proto === null) return false
if(proto === prototype) return true
proto = proto.__proto__;
}
}
★★★ 手写ajax
let xhq = new XMLHttpRequest()
xhq.open(methode, url, true)
xhq.send({
username:'wzx'
})
xhq.onreadystatechange = function () {
if ( xhq.readystate == 4 && xhq.status == 200 ) {
success(xhq.responseText)
} else if (xhq.readyState == 4 && xhq.status !== 200) {
error()
}
}
function sendAjax(obj) {
function splicStr(data) {
var str = ''
for (var i in data) {
str = i + '=' + data[i]
}
return str
}
let xhq = new XMLHttpRequest()
if (obj.method.toUpperCase() === 'GET') {
xhq.open(obj.method, obj.url + '?' + splicStr(obj.data), typeof obj.async === 'boolean'? obj.async : true)
xhq.send()
}
else if (obj.method.toUpperCase() === 'POST') {
xhq.open(obj.method, obj.url, typeof obj.async === 'boolean'? obj.async : true)
xhq.setRequestHeader("content-type","application/x-www-form-urlencoded")
xhq.send(obj.data)
}
xhq.onreadystatechange = function () {
if ( xhq.readyState == 4 && xhq.status == 200 ) {
success(xhq.responseText)
} else if (xhq.readyState == 4 && xhq.status !== 200) {
error()
}
}
}
sendAjax({
url: 'your url',
method: 'post',
async: true,
data: {
username: 'xiong',
pwd: '123'
},
success: function (data) {
console.log(data)
},
error: function () {
console.log('发生了错误')
}
})
★★★ 手写JSONP的原理和实现
function jsonp(url,data,callback){
var funcName = 'jsonp_'+Date.now()+Math.random().toString().substr(2, 5)
if(typeof data==='object'){
var tmpArr = []
for (let key in data){
let value =data[key]
tmpArr.push(key+'='+value)
}
data = tmpArr.join('&')
}
let script = document.createElement('script')
script.src = url + '?' + data + '&callback= ' + funcName
document.body.appendChild(script)
window[funcName]= function (data){
callback(data)
delete Window[funcName]
document.body.removeChild(script)
}
}
★★★★ 手写深拷贝
function deepCopy(obj){
return obj.JSON.Parse(JSON.Stringify(obj))
}
function deepCopy(obj){
if(typeof obj)
if(typeof obj =='object'){
var result = obj.constructor == Array?[]:{}
for(let i in obj){
result[i]= typeof obj[i] =='object'? deepCopy(obj[i]):obj[i]
}
}else{
var result = obj;
}
return result
}
★★★ 手写浅拷贝
function clone(target) {
if(target === null ) {
return target
}
let cloneTarget = Array.isArray(target) ? [] : {}
for (const key in target) {
if (target.hasOwnProperty(key)) {
cloneTarget[key] = target[key]
}
}
return cloneTarget
}
★★★★ 手写 bind
Function.prototype.myBind = function(context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
const _this = this
const args = [...arguments].slice(1)
return function F() {
if (this instanceof F) {
return new _this(...args, ...arguments)
}
return _this.apply(context, args.concat(...arguments))
}
}
★★★★ 手写 call
Function.prototype.myCall = function(context) {
context=context||window
context.fn = this
const args = [...arguments].slice(1)
const result = context.fn(...args)
delete context.fn
return result
}
★★★★ 手写 apply
Function.prototype.myApply = function(context) {
context = context || window
context.fn = this
let result
if(arguments[1]){
result = context.fn(...arguments[1])
}else{
result = context.fn()
}
delete context.fn
return result
}
★★★ 手写模拟 object.create
function _create (obj){
function F(){} //创建一个构造函数
F.prototype = obj //将构造函数的原型对象赋值
return new F()
}
★★★ 手写模拟 Object.is
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
}
}
console.log(is(+0, -0))
console.log(is(NaN, NaN))
★★★ 手写 new
function myNew(fn){
let obj = {}
obj = Object.create(fn.prototype)
let args = Array.prototype.slice.call(arguments,1)
let result = fn.call(obj,...args)
return typeof result === 'object'||result instanceof Function? result : obj;
}
class Foo{
constructor(){
this.name = 'ciel'
this.arg = arguments[0]
}
callname(){
console.log(this.name)
}
}
let test = myNew(Foo, 'hhh', '123', 'saf')
test.callName()
console.log(test.arg)
★★★ 手写对象扁平化
export function jsonFlatten(data) {
var result = {}
function recurse(cur, prop) {
if (Object(cur) !== cur) {
result[prop] = cur
} else if (Array.isArray(cur)) {
for (var i = 0, l = cur.length; i < l; i++) { recurse(cur[i], prop + '[' + i + ']') }
if (l === 0) { result[prop] = [] }
} else {
var isEmpty = true
for (var p in cur) {
isEmpty = false
recurse(cur[p], prop ? prop + '.' + p : p)
}
if (isEmpty && prop) { result[prop] = {} }
}
}
recurse(data, '')
return result
}
★★★ 手写数组扁平化
function flatten(arr){
let str = JSON.stringify(arr);
return str.replace(/(\[\]))/g,'').split(',')
}
function flatten(arr, result = []) {
if (!Array.isArray(arr)) {
result.push(arr)
return result
}
for (let value of arr) {
flatten(value, result)
}
return result
}
function flatten(arr) {
return arr.toString().split(',').map(ele => parseInt(ele))
}
function flatten(arr){
while(arr.some(item => Array.isArray(item))){
arr = [].concat(...arr);
}
return arr;
}
★★★ 手写数组去重
function unique(arr){
ruturn Array.from(new Set(arr))
}
function unique(arr) {
let result = []
for (let i = 0, len = arr.length; i < len; i++) {
let flag = false
for (let k = i + 1, len = arr.length; k < len; k++) {
if (arr[i] === arr[k]) {
flag = true
k = arr.length
}
}
if (!flag) result.push(arr[i])
}
return result
}
function unique(arr) {
let result = []
for (let i = 0, len = arr.length; i < len; i++) {
if (result.indexOf(arr[i]) === -1) result.push(arr[i])
}
return result
}
function unique(arr) {
let result = []
let bucket = [];
for (let i = 0, len = arr.length; i < len; i++) {
bucket[arr[i]] = 1
}
for (key in bucket) {
console.log(key);
result.push(Number(key))
}
return result
}
function unique(arr) {
return arr.filter((ele, index) => (arr.indexOf(ele) === index))
}
function unique(arr) {
return arr.map((ele, index) => {
if (arr.indexOf(ele) === index) return ele
})
}
function unique(arr) {
arr.sort()
let result = []
arr.forEach((ele, index) => {
if (ele !== arr[index + 1]) result.push(ele)
})
return result
}
★★★ 手写模拟实现 async/await
★★★★ 手写实现发布/订阅模式
class Subject {
constructor() {
this.observers = []
}
addObserver(observer) {
this.observers.push(observer)
}
removerObserver(observer) {
let index = this.observers.indexOf(observer)
if (index !== -1) {
this.observers.splice(index, 1)
}
}
notify() {
this.observers.forEach(observer => {
observer.update()
})
}
}
class Observer {
update() {
console.log('subject更新了');
}
subscribeTo(subject) {
subject.addObserver(this)
}
}
let subject = new Subject()
let observer1 = new Observer()
observer1.subscribeTo(subject)
let observer2 = new Observer()
observer2.subscribeTo(subject)
subject.notify()
★★★★ 手写防抖
funtion debounce(fn,delay){
let timer = null
return ()=>{
clearTimeout(timer)
timer = setTimeout(()=>(fn())
,delay)
}
}
let a = debounce(()=>(console.log('防抖处理')),500)
function 点击事件(){
a()
}
★★★★ 手写节流
function throttle(fn, delay = 500) {
let lastTime, time
return function(){
let context = this;
let args = [].slice.call(arguments);
time = Date.now()
if (!lastTime || time - lastTime > delay) {
fn.apply(context)
lastTime = time
}
}
}
function fn(){
console.log('节流')
}
let a = throttle(fn, 1000)
function 点击事件(){
a()
}