【成长之路】JavaScript中,模拟 call 的底层实现

【成长之路】JavaScript中,模拟 call 的底层实现_第1张图片

很多人都说IT人员的黄金年龄在 35岁以下,过了保质期就会被淘汰,但是,事实真的是这样吗?我见过40岁以上的IT人员,他们并没有被这个行业所淘汰,相反,他们可以比年轻的IT人员拥有更高的工作效率,因为他们有更多的开发经验,他们有更深的知识储备,他们一直在充实自己,给自己充电。因为他们明白,不努力,不充实自己,不紧跟技术的发展,被淘汰是早晚的事情。

从事前端工作三年多,工作有忙也有闲,闲的时候也会学习给自己充电,但是,总是感觉学的多,忘得更多,总是感觉自己在抓不到重点的学,每天感觉都很迷茫,感觉自己对于好多的知识都很模糊,虽然知道的多,了解的多,但是好多东西其实只是学到了皮毛。参加【拉勾教育 大前端高薪训练营】已经两个多月了,每天听完课以后,都会记笔记,然后通过 博客,我感觉这种方式很好,在写博客的过程中,我会把每天学习的新的知识点再看一遍,这样的话,知识可以更加深刻的记录在脑海里。

在没有加入【拉勾教育 大前端高薪训练营】之前,我根本不知道什么叫函数式编程,什么是宏任务和微任务,什么是 虚拟 DOM, Vue 的底层代码是如何实现的,也不知道 call 的底层实现。现在,通过课程的学习,我知道该如何去使用他们,通过对 虚拟DOM 的学习,我知道该如何去分析其他框架。这些底层东西的学习,可以帮助我很好的学习 Vue、React 等。我现在刚刚学完Vue 的源码,了解了Vue 的底层实现机制,在使用Vue时,就会更加的得心应手。并且,除了一些特定的课程以外,在每次直播的时候,都会有加餐加餐的内容可能是一些开发中的小技巧,也可能是一些最新的技术,还可能是一些重点难点的讲解,这些都可以让我更好的成长,收获更多。

在后期还会学习 React 源码、Vue 3.0 新特性、Node.js 、GraphQL 等课程,我相信当学完的时候,一定会与现在的我不一样,至少我的知识储备相较于现在,会得到更大程度的扩充。

下面,是我的一篇模拟 call 的底层实现的blog,欢迎朋友们查阅和指出不足之处。

JavaScript中,模拟 call 的底层实现

笔记来源:拉勾教育 大前端高薪训练营

面试题

function fn1 () {
     
    console.log(1)
}

function fn2 () {
     
    console.log(2)
}

// call 的作用
// 调用 call fn1函数,并改变fn1内部的this,将 this 指向 fn2
fn1.call(fn2)   // 1
fn1.call.call(fn2) // 2

模拟 call 的实现

没有传参

// 让所有的函数对象,都具有 mycall 方法
// context.fn1()
Function.prototype.mycall = function mycall(context, ...args) {
     
    // context = context || window
    // ?? 
    // 只有 context 的值是 null 或者 undefined 的时候,才会返回 window
    context = context ?? window
    // 此处的 this 指向的是 fn1 函数
    // 临时把 this 存储进 context.fn 中
    context.fn = this
    const result = context.fn(...args)

    delete context.fn
    return result
}

执行过程

// fn1.mycall.mycall(fn2),执行过程
Function.prototype.mycall = function mycall(context, ...args) {
     
	// context ---> fn2
    context = context ?? window
    // context.fn ---> this ---> mycall
    // fn2.mycall
    context.fn = this
    // 暂停,等待执行 fn2.mycall (没有参数)
    const result = context.fn(...args)

    delete context.fn
    return result
}

// 调用 fn2.mycalll (没传参数)
Function.prototype.mycall = function mycall(context, ...args) {
     
	// context ---> Window
    context = context ?? window
    // context.fn ---> this ---> fn2
    // window.fn2
    context.fn = this
    // window.fn2 (没有参数)
    const result = context.fn(...args)

    delete context.fn
    return result
}

传入参数

// context.fn1()
Function.prototype.mycall = function mycall(context, ...args) {
     
    // 此处要去处理 context 是原始值的问题
    switch (typeof context) {
     
        case 'number':
            context = new Number(context)
            break
        case 'string':
            context = new String(context)
            break
        case 'boolean':
            context = new Boolean(context)
            break
        default:
            // context = context || window
            context = context ?? window
    }

            // 此处的 this 指向的是 fn1 函数
            // 临时把 this 存储进 context.fn 中
            context.fn = this
            const result = context.fn(...args)

            delete context.fn
            return result
    }

    const obj = {
      name: 'zs' }
    // fn1.mycall(obj)
    fn1.mycall.mycall(fn2, "1", 2)
}

知乎地址

https://zhuanlan.zhihu.com/p/342232134

你可能感兴趣的:(难点集锦,前端笔记,javascript)