2024年前端最全史上最全,熬夜整理56个JavaScript高级的手写知识点,专业扫盲,2024年最新特殊渠道拿到阿里大厂面试真题

结尾

正式学习前端大概 3 年多了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多,但是每一本都是那种看一本就秒不绝口的感觉。

以下大部分是我看过的,或者说身边的人推荐的书籍,每一本我都有些相关的推荐语,如果你有看到更好的书欢迎推荐呀。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

前端学习书籍导图-1

}

}

once(name, cb) {

function fn(…args) {

cb(args)

this.off(name, fn)

}

this.on(name, fn)

}

}

13、实现JSON.parse

题目描述:实现JSON.parse

function parse (json) {

return eval(“(” + json + “)”);

}

14、将DOM转化成树结构对象

题目描述:

    • 将上方的DOM转化为下面的树结构对象

      {

      tag: ‘DIV’,

      children: [

      { tag: ‘SPAN’, children: [] },

      {

      tag: ‘UL’,

      children: [

      { tag: ‘LI’, children: [] },

      { tag: ‘LI’, children: [] }

      ]

      }

      ]

      }

      实现如下:

      function dom2tree(dom) {

      const obj = {}

      obj.tag = dom.tagName

      obj.children = []

      dom.childNodes.forEach(child => obj.children.push(dom2tree(child)))

      return obj

      }

      15、将树结构转换为DOM

      题目描述:

      {

      tag: ‘DIV’,

      children: [

      { tag: ‘SPAN’, children: [] },

      {

      tag: ‘UL’,

      children: [

      { tag: ‘LI’, children: [] },

      { tag: ‘LI’, children: [] }

      ]

      }

      ]

      }

      将上方的树结构对象转化为下面的DOM

      • 实现如下:

        // 真正的渲染函数

        function _render(vnode) {

        // 如果是数字类型转化为字符串

        if (typeof vnode === “number”) {

        vnode = String(vnode);

        }

        // 字符串类型直接就是文本节点

        if (typeof vnode === “string”) {

        return document.createTextNode(vnode);

        }

        // 普通DOM

        const dom = document.createElement(vnode.tag);

        if (vnode.attrs) {

        // 遍历属性

        Object.keys(vnode.attrs).forEach((key) => {

        const value = vnode.attrs[key];

        dom.setAttribute(key, value);

        });

        }

        // 子数组进行递归操作

        vnode.children.forEach((child) => dom.appendChild(_render(child)));

        return dom;

        }

        16、判断一个对象有环引用

        题目描述:验证一个对象有无环引用

        var obj = {

        a: {

        c: [

        1, 2

        ]

        },

        b: 1

        }

        obj.a.c.d = obj

        console.log(cycleDetector(obj)) // true

        实现思路:用一个数组存储每一个遍历过的对象,下次找到数组中存在,则说明环引用

        function cycleDetector(obj) {

        const arr = [obj]

        let flag = false

        function cycle(o) {

        const keys = Object.keys(o)

        for (const key of keys) {

        const temp = o[key]

        if (typeof temp === ‘object’ && temp !== null) {

        if (arr.indexOf(temp) >= 0) {

        flag = true

        return

        }

        arr.push(temp)

        cycle(temp)

        }

        }

        }

        cycle(obj)

        return flag

        }

        17、计算一个对象的层数

        题目描述:给你一个对象,统计一下它的层数

        const obj = {

        a: { b: [1] },

        c: { d: { e: { f: 1 } } }

        }

        console.log(loopGetLevel(obj)) // 4

        实现如下:

        function loopGetLevel(obj) {

        var res = 1;

        function computedLevel(obj, level) {

        var level = level ? level : 0;

        if (typeof obj === ‘object’) {

        for (var key in obj) {

        if (typeof obj[key] === ‘object’) {

        computedLevel(obj[key], level + 1);

        } else {

        res = level + 1 > res ? level + 1 : res;

        }

        }

        } else {

        res = level > res ? level : res;

        }

        }

        computedLevel(obj)

        return res

        }

        18、对象的扁平化

        题目描述:

        const obj = {

        a: {

        b: 1,

        c: 2,

        d: {e: 5}

        },

        b: [1, 3, {a: 2, b: 3}],

        c: 3

        }

        flatten(obj) 结果返回如下

        // {

        // ‘a.b’: 1,

        // ‘a.c’: 2,

        // ‘a.d.e’: 5,

        // ‘b[0]’: 1,

        // ‘b[1]’: 3,

        // ‘b[2].a’: 2,

        // ‘b[2].b’: 3

        // c: 3

        // }

        实现如下:

        const isObject = (val) => typeof val === “object” && val !== null

        function flatten(obj) {

        if (!isObject(obj)) return

        const res = {}

        const dfs = (cur, prefix) => {

        if (isObject(cur)) {

        if (Array.isArray(cur)) {

        cur.forEach((item, index) => {

        dfs(item, ${prefix}[${index}])

        })

        } else {

        for(let key in cur) {

        dfs(cur[key], ${prefix}${prefix ? '.' : ''}${key})

        }

        }

        } else {

        res[prefix] = cur

        }

        }

        dfs(obj, ‘’)

        return res

        }

        // 测试

        console.log(flatten(obj))

        19、实现(a == 1 && a == 2 && a == 3)为true

        题目描述:实现(a == 1 && a == 2 && a == 3)为true

        // 第一种方法

        var a = {

        i: 1,

        toString: function () {

        return a.i++;

        }

        }

        console.log(a == 1 && a == 2 && a == 3) // true

        // 第二种方法

        var a = [1, 2, 3];

        a.join = a.shift;

        console.log(a == 1 && a == 2 && a == 3); // true

        // 第三种方法

        var val = 0;

        Object.defineProperty(window, ‘a’, {

        get: function () {

        return ++val;

        }

        });

        console.log(a == 1 && a == 2 && a == 3) // true

        20、实现限制并发的Promise调度器

        题目描述:JS 实现一个带并发限制的异步调度器 Scheduler,保证同时运行的任务最多有两个

        addTask(1000,“1”);

        addTask(500,“2”);

        addTask(300,“3”);

        addTask(400,“4”);

        的输出顺序是:2 3 1 4

        整个的完整执行流程:

        一开始1、2两个任务开始执行

        500ms时,2任务执行完毕,输出2,任务3开始执行

        800ms时,3任务执行完毕,输出3,任务4开始执行

        1000ms时,1任务执行完毕,输出1,此时只剩下4任务在执行

        1200ms时,4任务执行完毕,输出4

        实现如下:

        class Scheduler {

        constructor(limit) {

        this.queue = []

        this.limit = limit

        this.count = 0

        }

        add(time, order) {

        const promiseCreator = () => {

        return new Promise((resolve, reject) => {

        setTimeout(() => {

        console.log(order)

        resolve()

        }, time)

        })

        }

        this.queue.push(promiseCreator)

        }

        taskStart() {

        for(let i = 0; i < this.limit; i++) {

        this.request()

        }

        }

        request() {

        if (!this.queue.length || this.count >= this.limit) return

        this.count++

        this.queue.shift()().then(() => {

        this.count–

        this.request()

        })

        }

        }

        // 测试

        const scheduler = new Scheduler(2);

        const addTask = (time, order) => {

        scheduler.add(time, order);

        };

        addTask(1000, “1”);

        addTask(500, “2”);

        addTask(300, “3”);

        addTask(400, “4”);

        scheduler.taskStart();

        21、实现lazyMan函数

        题目描述:

        实现一个LazyMan,可以按照以下方式调用:

        LazyMan(“Hank”)输出:

        Hi! This is Hank!

        LazyMan(“Hank”).sleep(10).eat(“dinner”)输出

        Hi! This is Hank!

        //等待10秒…

        Wake up after 10

        Eat dinner~

        LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出

        Hi This is Hank!

        Eat dinner~

        Eat supper~

        LazyMan(“Hank”).eat(“supper”).sleepFirst(5)输出

        //等待5秒

        Wake up after 5

        Hi This is Hank!

        Eat supper

        实现如下:

        class _LazyMan {

        constructor(name) {

        this.tasks = []

        const task = () => {

        console.log(Hi! This is ${name})

        this.next()

        }

        this.tasks.push(task)

        setTimeout(() => {

        this.next()

        }, 0)

        }

        next() {

        const task = this.tasks.shift()

        task && task()

        }

        sleep(time) {

        this.sleepWrapper(time, false)

        return this

        }

        sleepFirst(time) {

        this.sleepWrapper(time, true)

        return this

        }

        sleepWrapper(time, first) {

        const task = () => {

        setTimeout(() => {

        console.log(Wake up after ${time})

        this.next()

        }, time * 1000)

        }

        if (first) {

        this.tasks.unshift(task)

        } else {

        this.tasks.push(task)

        }

        }

        eat(food) {

        const task = () => {

        console.log(Eat ${food});

        this.next();

        };

        this.tasks.push(task);

        return this;

        }

        }

        // 测试

        const lazyMan = (name) => new _LazyMan(name)

        lazyMan(‘Hank’).sleep(1).eat(‘dinner’)

        lazyMan(‘Hank’).eat(‘dinner’).eat(‘supper’)

        lazyMan(‘Hank’).eat(‘supper’).sleepFirst(5)

        22、实现add函数

        题目描述:实现一个 add 方法 使计算结果能够满足如下预期:

        • add(1)(2)(3)()=6
        • add(1,2,3)(4)()=10

        function add(…args1) {

        let allArgs = […args1]

        function fn(…args2) {

        if (!args2.length) return fn.toString()

        allArgs = […allArgs, …args2]

        return fn

        }

        fn.toString = function () {

        return allArgs.reduce((pre, next) => pre + next)

        }

        return fn

        }

        // 测试

        console.log(add(1)(2)(3)())

        console.log(add(1, 2)(3)())

        23、实现一个合格的深拷贝

        24、实现 Promise

        25、实现 async/await

        Array篇


        定义一个测试数组

        const players = [

        { name: ‘科比’, num: 24 },

        { name: ‘詹姆斯’, num: 23 },

        { name: ‘保罗’, num: 3 },

        { name: ‘威少’, num: 0 },

        { name: ‘杜兰特’, num: 35 }

        ]

        26、forEach

        参数代表含义

        • item:遍历项

        • index:遍历项的索引

        • arr:数组本身

        Array.prototype.sx_forEach = function (callback) {

        for (let i = 0; i < this.length; i++) {

        callback(this[i], i, this)

        }

        }

        players.sx_forEach((item, index, arr) => {

        console.log(item, index)

        })

        // { name: ‘科比’, num: 24 } 0

        // { name: ‘詹姆斯’, num: 23 } 1

        // { name: ‘保罗’, num: 3 } 2

        // { name: ‘威少’, num: 0 } 3

        // { name: ‘杜兰特’, num: 35 } 4

        27、map

        参数代表含义

        • item:遍历项

        • index:遍历项的索引

        • arr:数组本身

        Array.prototype.sx_map = function (callback) {

        const res = []

        for (let i = 0; i < this.length; i++) {

        res.push(callback(this[i], i, this))

        }

        return res

        }

        console.log(players.sx_map((item, index) => ${item.name}--${item.num}--${index}))

        // [ ‘科比–24–0’, ‘詹姆斯–23–1’, ‘保罗–3–2’, ‘威少–0–3’, ‘杜兰特–35–4’ ]

        28、filter

        参数代表含义

        • item:遍历项

        • index:遍历项的索引

        • arr:数组本身

        Array.prototype.sx_filter = function (callback) {

        const res = []

        for (let i = 0; i < this.length; i++) {

        callback(this[i], i, this) && res.push(this[i])

        }

        return res

        }

        console.log(players.sx_filter(item => item.num >= 23))

        // [

        // { name: ‘科比’, num: 24 },

        // { name: ‘詹姆斯’, num: 23 },

        // { name: ‘杜兰特’, num: 35 }

        // ]

        29、every

        参数代表含义

        • item:遍历项

        • index:遍历项的索引

        • arr:数组本身

        Array.prototype.sx_every = function (callback) {

        let flag = true

        for (let i = 0; i < this.length; i++) {

        flag = callback(this[i], i, this)

        if (!flag) break

        }

        return flag

        }

        console.log(players.sx_every(item => item.num >= 23)) // false

        console.log(players.sx_every(item => item.num >= 0)) // true

        30、some

        参数代表含义

        • item:遍历项

        • index:遍历项的索引

        • arr:数组本身

        Array.prototype.sx_some = function (callback) {

        let flag = false

        for (let i = 0; i < this.length; i++) {

        flag = callback(this[i], i, this)

        if (flag) break

        }

        return flag

        }

        console.log(players.sx_some(item => item.num >= 23)) // true

        console.log(players.sx_some(item => item.num >= 50)) // false

        31、reduce

        参数代表含义

        • pre:前一项

        • next:下一项

        • index:当前索引

        • arr:数组本身

        Array.prototype.sx_reduce = function (callback, …args) {

        let start = 0, pre

        if (args.length) {

        pre = args[0]

        } else {

        pre = this[0]

        start = 1

        }

        for (let i = start; i < this.length; i++) {

        pre = callback(pre, this[i], i, this)

        }

        return pre

        }

        // 计算所有num相加

        const sum = players.sx_reduce((pre, next) => {

        return pre + next.num

        }, 0)

        console.log(sum) // 85

        32、findIndex

        参数代表含义

        • item:遍历项

        • index:遍历项的索引

        • arr:数组本身

        Array.prototype.sx_findIndex = function (callback) {

        for (let i = 0; i < this.length; i++) {

        if (callback(this[i], i, this)) {

        return i

        }

        }

        return -1

        }

        console.log(players.sx_findIndex(item => item.name === ‘科比’)) // 0

        console.log(players.sx_findIndex(item => item.name === ‘安东尼’)) // -1

        33、find

        参数代表含义

        • item:遍历项

        • index:遍历项的索引

        • arr:数组本身

        Array.prototype.sx_find = function (callback) {

        for (let i = 0; i < this.length; i++) {

        if (callback(this[i], i, this)) {

        return this[i]

        }

        }

        return undefined

        }

        console.log(players.sx_find(item => item.name === ‘科比’)) // { name: ‘科比’, num: 24 }

        console.log(players.sx_find(item => item.name === ‘安东尼’)) // undefined

        34、fill

        用处:填充数组

        参数代表含义

        • initValue:填充的值

        • start:开始填充索引,默认0

        • end:结束填充索引,默认length

        Array.prototype.sx_fill = function (value, start = 0, end) {

        end = end || this.length

        for (let i = start; i < end; i++) {

        this[i] = value

        }

        return this

        }

        console.log(players.sx_fill(‘林三心’, 1, 3))

        // [

        // { name: ‘科比’, num: 24 },

        // ‘林三心’,

        // ‘林三心’,

        // ‘林三心’,

        // { name: ‘杜兰特’, num: 35 }

        // ]

        35、includes

        用处:查找元素,查到返回true,反之返回false,可查找NaN

        Array.prototype.sx_includes = function (value, start = 0) {

        if (start < 0) start = this.length + start

        const isNaN = Number.isNaN(value)

        for (let i = start; i < this.length; i++) {

        if (this[i] === value || (isNaN && Number.isNaN(this[i])) {

        return true

        }

        }

        return false

        }

        console.log([1, 2, 3].sx_includes(2)) // true

        console.log([1, 2, 3, NaN].sx_includes(NaN)) // true

        console.log([1, 2, 3].sx_includes(1, 1)) // false

        36、join

        用处:将数组用分隔符拼成字符串,分隔符默认为,

        Array.prototype.sx_join = function (s = ‘,’) {

        let str = ‘’

        for(let i = 0; i < this.length; i++) {

        str = i === 0 ? ${str}${this[i]} : ${str}${s}${this[i]}

        }

        return str

        }

        console.log([1, 2, 3].sx_join()) // 1,2,3

        console.log([1, 2, 3].sx_join('')) // 12*3

        37、flat

        Array.prototype.sx_flat = function (num = Infinity) {

        let arr = this

        let i = 0

        while (arr.some(item => Array.isArray(item))) {

        arr = [].concat(…arr)

        i++

        if (i >= num) break

        }

        return arr

        }

        const testArr = [1, [2, 3, [4, 5]], [8, 9]]

        console.log(testArr.sx_flat(1))

        // [1, 2, 3, 4, 5, 8, 9]

        38、splice

        难点

        • 截取长度和替换长度的比较,不同情况

        Array.prototype.sx_splice = function (start, length, …values) {

        if (length === 0) return []

        length = start + length > this.length - 1 ? this.length - start : length

        console.log(length)

        const res = [], tempArr = […this]

        for (let i = start; i < start + values.length; i++) {

        this[i] = values[i - start]

        }

        this.length = start + values.length

        if (values.length < length) {

        const cha = length - values.length

        console.log(cha)

        for (let i = start + values.length; i < tempArr.length; i++) {

        this[i] = tempArr[i + cha]

        }

        this.length = this.length - cha

        }

        if (values.length > length) {

        for (let i = start + length; i < tempArr.length; i++) {

        this.push(tempArr[i])

        }

        }

        for (let i = start; i < start + length; i++) {

        res.push(tempArr[i])

        }

        return res

        }

        Object篇


        定义一个测试对象

        const obj = {

        name: ‘林三心’,

        age: 22,

        gender: ‘男’

        }

        39、entries

        用处:将对象转成键值对数组

        Object.prototype.sx_entries = function (obj) {

        const res = []

        for (let key in obj) {

        obj.hasOwnProperty(key) && res.push([key, obj[key]])

        }

        return res

        }

        console.log(Object.sx_entries(obj))

        // [ [ ‘name’, ‘林三心’ ], [ ‘age’, 22 ], [ ‘gender’, ‘男’ ] ]

        40、fromEntries

        用处:跟entries相反,将键值对数组转成对象

        Object.prototype.sx_fromEntries = function (arr) {

        const obj = {}

        for (let i = 0; i < arr.length; i++) {

        const [key, value] = arr[i]

        obj[key] = value

        }

        return obj

        }

        console.log(Object.sx_fromEntries([[‘name’, ‘林三心’], [‘age’, 22], [‘gender’, ‘男’]]))

        // { name: ‘林三心’, age: 22, gender: ‘男’ }

        41、keys

        用处:将对象的key转成一个数组合集

        Object.prototype.sx_keys = function (obj) {

        const keys = []

        for (let key in obj) {

        obj.hasOwnProperty(key) && res.push(key)

        }

        return keys

        }

        console.log(Object.keys(obj))

        // [ ‘name’, ‘age’, ‘gender’ ]

        42、values

        用处:将对象的所有值转成数组合集

        Object.prototype.sx_values = function (obj) {

        const values = []

        for (let key in obj) {

        obj.hasOwnProperty(key) && values.push(obj[key])

        }

        return values

        }

        console.log(Object.sx_values(obj))

        // [ ‘林三心’, 22, ‘男’ ]

        43、instanceOf

        用处:A instanceOf B,判断A是否经过B的原型链

        function instanceOf(father, child) {

        const fp = father.prototype

        var cp = child.proto

        while (cp) {

        if (cp === fp) {

        return true

        }

        cp = cp.proto

        }

        return false

        }

        function Person(name) {

        this.name = name

        }

        const sx = new Person(‘林三心’)

        console.log(instanceOf(Person, sx)) // true

        console.log(instanceOf(Person, sx2)) // false

        44、is

        用处:Object.is(a, b),判断a是否等于b

        Object.prototype.sx_is = function (x, y) {

        if (x === y) {

        // 防止 -0 和 +0

        return x !== 0 || 1 / x === 1 / y

        }

        // 防止NaN

        return x !== x && y !== y

        }

        const a = { name: ‘林三心’ }

        const b = a

        const c = { name: ‘林三心’ }

        console.log(Object.sx_is(a, b)) // true

        console.log(Object.sx_is(a, c)) // false

        45、Object.assign

        难点

        • assign接收多个对象,并将多个对象合成一个对象

        • 这些对象如果有重名属性,以后来的对象属性值为准

        • assign返回一个对象,这个对象 === 第一个对象

        Object.prototype.sx_assign = function (target, …args) {

        if (target === null || target === undefined) {

        throw new TypeError(‘Cannot convert undefined or null to object’)

        }

        target = Object(target)

        for (let nextObj of args) {

        for (let key in nextObj) {

        nextObj.hasOwnProperty(key) && (target[key] = nextObj[key])

        结尾

        学习html5、css、javascript这些基础知识,学习的渠道很多,就不多说了,例如,一些其他的优秀博客。但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。

        开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

        html5

        用处:将对象的所有值转成数组合集

        Object.prototype.sx_values = function (obj) {

        const values = []

        for (let key in obj) {

        obj.hasOwnProperty(key) && values.push(obj[key])

        }

        return values

        }

        console.log(Object.sx_values(obj))

        // [ ‘林三心’, 22, ‘男’ ]

        43、instanceOf

        用处:A instanceOf B,判断A是否经过B的原型链

        function instanceOf(father, child) {

        const fp = father.prototype

        var cp = child.proto

        while (cp) {

        if (cp === fp) {

        return true

        }

        cp = cp.proto

        }

        return false

        }

        function Person(name) {

        this.name = name

        }

        const sx = new Person(‘林三心’)

        console.log(instanceOf(Person, sx)) // true

        console.log(instanceOf(Person, sx2)) // false

        44、is

        用处:Object.is(a, b),判断a是否等于b

        Object.prototype.sx_is = function (x, y) {

        if (x === y) {

        // 防止 -0 和 +0

        return x !== 0 || 1 / x === 1 / y

        }

        // 防止NaN

        return x !== x && y !== y

        }

        const a = { name: ‘林三心’ }

        const b = a

        const c = { name: ‘林三心’ }

        console.log(Object.sx_is(a, b)) // true

        console.log(Object.sx_is(a, c)) // false

        45、Object.assign

        难点

        • assign接收多个对象,并将多个对象合成一个对象

        • 这些对象如果有重名属性,以后来的对象属性值为准

        • assign返回一个对象,这个对象 === 第一个对象

        Object.prototype.sx_assign = function (target, …args) {

        if (target === null || target === undefined) {

        throw new TypeError(‘Cannot convert undefined or null to object’)

        }

        target = Object(target)

        for (let nextObj of args) {

        for (let key in nextObj) {

        nextObj.hasOwnProperty(key) && (target[key] = nextObj[key])

        结尾

        学习html5、css、javascript这些基础知识,学习的渠道很多,就不多说了,例如,一些其他的优秀博客。但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。

        开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

        [外链图片转存中…(img-Du6Gwx7X-1715530153787)]

      • 28
        点赞
      • 11
        收藏
        觉得还不错? 一键收藏
      • 0
        评论
      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

      当前余额3.43前往充值 >
      需支付:10.00
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包
      实付
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

      余额充值