1.柯里化
function argsSum(args) {
return args.reduce((pre, cur) => {
return pre + cur
})
}
function add(...args1) {
let sum1 = argsSum(args1)
let fn = function (...args2) {
let sum2 = argsSum(args2)
return add(sum1 + sum2)
}
fn.toString = function () {
return sum1
}
return fn
}
2.手寫 instanceof
思路:a 沿著原型鏈找到 b.prototype,則 a instanceof b = true,遍歷 a 的原型鏈,找到 b.prototype,返回 true,否則返回 false
const my_instanceof = (A, B) => {
let p = A //指針指向a
while (p) {
//遍歷原型鏈
if (p === B.prototype) {
return true
}
p = p.__proto__
}
return false
}
3.深克隆
function clone(data) {
if (typeof data === 'symbol') {
//symbol,symbol是非object的基本類型
return Symbol().for(data.description)
} else if (typeof data != 'object') {
//基本類型
return data
} else if (data instanceof Array) {
// Array
return data.map(i => clone(i))
} else if (data.constructor === Object) {
//避免 new Date,處理json
let res = {}
for (let key in data) {
res[key] = clone(data[key])
}
return res
} else {
//系統(tǒng)對象及自定義對象 類似于class
return new data.constructor(data)
}
}
4.手寫bind
function _bind(asThis) {
var fn = this //記錄this
var args = slice.call(arguments, 1)
if (typeof fn != 'function') {
throw new Error('bind需使用在函數(shù)上')
}
function resFn() {
var args2 = slice.call(arguments, 0)
return fn.apply(
resFn.prototype.isPrototypeOf(this) ? this : asThis,
args.concat(args2))
}
resFn.prototype = fn.prototype
return resFn
}
5.手寫new
function new_operator(_constructor, ...args) {
// ① 創(chuàng)建新對象obj,并關(guān)聯(lián)obj原型到構(gòu)造函數(shù)原型對象上
let obj = Object.create(_constructor.prototype)
// ② 執(zhí)行構(gòu)造函數(shù),且綁定this到新對象Obj上,實(shí)現(xiàn)繼承。同時(shí)接受返回值res
let res = _constructor.apply(obj, args)
// ③ 返回值判斷
return res instanceof Object ? res : obj
}
6.手寫Promise.race
Promise.myRace = arr => {
return new Promise((resolve, reject) => {
arr.forEach(p => p.then(resolve, reject))
})
}
//Promise.any(誰先成功)比Promise.race(誰先完成)好用
7.手寫Promise.all
Promise.myall = promises => {
let complete = 0
let result = []
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(res => {
complete++
result[i]= res
if (complete == promises.length) {
resolve(result)
}
}, reject)
}
})
}
8.(京東快手)兩數(shù)之和
示例:nums = [2,7,11,15] target = 9 //輸出[0,1]
思路:nums 去相親者,target 匹配的條件,字典建立一個(gè)介紹所儲存相親者的數(shù)字和下標(biāo)
//obj解法
let nums = [2, 7, 11, 15],
target = 9;
function Two(nums, target) {
const obj = {}
for (let i = 0; i < nums.length; i++) {
let a = nums[i]
let b = target - a
if (obj[b] != undefined) {
return [obj[b], i]
} else {
obj[a] = i
}
}
return null
}
//時(shí)間復(fù)雜度和空間復(fù)雜度都是O(n)
//Map解法
var twoSum = function (nums, target) {
let map = new Map()
for (let i = 0; i < nums.length; i++) {
const n = nums[i]
const n2 = target - n // 符合匹配條件的選手
if (map.has(n2)) {
return [map.get(n2), i] // 返回符合條件對象的下標(biāo),自身下標(biāo)
} else {
map.set(n, i)
}
}
}
//時(shí)間復(fù)雜度 O(n)//空間復(fù)雜度 O(n)//線性
9. 兩個(gè)數(shù)組的交集 題號 349
Map 解題思路,新建立一個(gè)字典,遍歷 nums1,填充字典,遍歷 nums2,遇到字典值就選出,并從字典里刪除
var intersection = function (nums1, nums2) {
const map = new Map()
nums1.forEach(n => {
map.set(n, true) //代表這個(gè)值在字典里存在
})
let res = []
nums2.forEach(n => {
if (map.get(n)) {
res.push(n)
map.delete(n)
}
})
return res
}
//時(shí)間復(fù)雜度O(n+m)
//空間復(fù)雜度指臨時(shí)變量內(nèi)存消耗 O(m)
10.拍平數(shù)組,去除重復(fù)部分,得到升序不重復(fù)數(shù)組,[[1,2,2],[3,4,5,5],[6,7,8,9[11,12,[12,13,[14]]]],10]
flat1(arr5)
function flat1(a) {
let res = []
let json = {}
//拍平并去重
for (let i = 0; i < a.length; i++) {
if (typeof a[i] == 'number') {
// if(!res.includes(a[i])){//低性能版
// res.push(a[i])
// }
if (!json[a[i]]) {
//高性能
res.push(a[i])
json[a[i]] = true
}
} else {
flat1(a[i])
}
}
}
11.爬樓梯 70 dp問題
定義子問題f(n) = f(n-1) + f(n-2)
反復(fù)執(zhí)行 從2循環(huán)到n,執(zhí)行上述公式
var clibStairs2 = function (n) {
if (n < 2) {
return 1
}
let dp0 = 1
let dp1 = 1
for (let i = 2; i < n; i++) {
const tmp = dp0
dp0 = dp1
dp1 = dp1 + tmp
}
return dp1
}
//時(shí)間復(fù)雜度 o(n)
//空間復(fù)雜度 o(n)
12.變態(tài)版青蛙跳臺階 dp問題
function jump(n){
if(n<0){
return -1
}else if(n==1){
return 1
}else{
return 2*jump(n-1)
}
}
13. 環(huán)形鏈表,題號 141
解題思路:有一快一慢兩個(gè)指針遍歷鏈表,指針可以相逢,說明有環(huán),返回 true,兩個(gè)指針不相逢就說明沒有環(huán),返回 false
var hasCycle = function (head) {
let p1 = head //慢指針
let p2 = head //快指針
while (p1 && p2 && p2.next) {
p1 = p1.next //走一步
p2 = p2.next.next //走兩步
if (p1 === p2) {
//兩個(gè)指針是否重逢
return true
}
}
return false
}
//有while循環(huán),時(shí)間復(fù)雜度 O(n)
//空間復(fù)雜度:O(1)。因無線性增長結(jié)構(gòu),矩陣,列表
14.旋轉(zhuǎn)數(shù)組 189
function shift(arr, k) {
k %= arr.length
if (k >= Math.floor(arr.length / 2)) {
arr.push(...arr.splice(0, arr.length - k))
} else {
arr.unshift(...arr.splice(arr.length - k, k))
}
return arr
}
15.實(shí)現(xiàn) sleep 函數(shù),等待 1000ms,可以從 promise、generator、async 角度實(shí)現(xiàn),本意問實(shí)現(xiàn) promise
function sleep(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms)
})
}
;(async () => {
console.log(11)
await sleep(2000)
console.log(22)
})()