谈谈隐式调用的实际用途

899 阅读2分钟

一、前言

前端神级dom框架-JQuery的介绍

jq中,使用的最多的便是dom操作,在三大框架还没普及之前,前端基本都是jq一把梭的时代,其核心思想便是链式调用,即无需分步操作同一个dom元素,下面会围绕JQuery进行隐式调用的阐述

二、正文

jq一把梭

作为老一辈的前端er应该知道,$()造就了一堆前端英雄豪杰,比如,想要获取表单元素li,并设置其字体为白色,添加名为‘todoList’的class,原生的dom操作写法为

// get dom named li and set its attribute and css stayle
const $li = document.getElementsByTagName('li')
$li.style.color = '#fff'
$li.setAttribute('class', 'todoList')

JQuery的写法

//jq一把梭
$('li').css('color', '#fff').attr('class', 'todoList')

这tm就是革命性的进步啊!原来分三步的逻辑,jq一句话就给你搞定了。嫌话少扯,下面进入第二节,开始今天的主要内容阐述

隐式调用的用途

在前一节的阐述中,我们可以看到,jq一句话就把之前三步才能实现的操作,一次性就解决了,下面我们来模拟看看其对应代码是如何实现的

const $ = element => {
    const nodes = document.querySelectorAll(element)
    nodes.attr = (key, value) => {
        nodes.forEach(node => node.settAttribute(key, value))
        return nodes
    }
    nodes.css = (key, value) => {
        nodes.forEach(node => node.style[key] = value)
        return nodes
    }
    return nodes
}

注意看attrcss这两个函数的实现,最后都把nodesreturn了,才让链式调用得以实现,有的同学就会说,这不是很简单嘛,一点难度都没有,让我来我也会,确实,jq的实现可以说没有啥难度,又或者说难度不在于链式调用的实现(可能是兼容性之类的),但是大家应该知道,像G = mg这样的公式理解起来,也不难,真正难的,是对其原理的深度解剖,下面我们来看个例子

// 实现一个函数add,使其能得出下列结果1add(1)(2)(3) == 6 // true2add(1)(2)(3)(4) == 10 // true

可以肯定的是,这道题对于不清楚隐式调用的同学来讲,几乎无法实现(目前没想到其他实现方法,但不代表没有,只能代表本人才疏学浅),其实,这跟jq的链式调用是同一种思想,都是实现了连锁式编程,但是这道题,难度在于不能像jq那样如此简单的直接返回某一个东西就能得到我们想要的结果,卖了这么多关子,终于到了我们今天的主题--隐式调用,下面来看看例题的解法

const add = num => {
    let myNum = num
    const newAdd = newNum => {
        myNum += newNum
        return newAdd
    }
    newAdd.valueOf = () => myNum
    return newAdd
}

看上去跟jq的实现原理是挺像的,但是最让人费解的部分应该在于,为啥这样就能实现题目的效果?奥妙便是在这valueOf中,在将基本类型引用类型进行比较时,引用类型的valueOf会被隐式调用,本题中即是newAdd的valueOf被调用了,因为我们将其函数重写,最后便能得到题目中的效果。

===是直接判断变量的地址,因此只能用于双等该题目才能成立,除valueOf之外,还有toString也能隐式调用!

三、总结

涉及到操作符的问题,valueOftoString会被隐式调用,不同的是,valueOf的优先级比toString的优先级高,涉及到显示问题,toString方法优先级比valueOf方法高

拓展练习

// 编写一个对象`obj`,使其能实现如下效果
typeof obj == 'object' && obj == 2 // true

今天的摸鱼到此结束!谢谢观看!