2-0 【函数科里化与渲染模型】

213 阅读3分钟

一、什么是函数科里化

1. 函数科里化定义

一个函数原本有多个参数,先传入 一个 参数,然后生成一个新函数,由新函数接收剩下的参数来运行得到结构。

二、 为什么要用函数科里化

为了提高性能,使用科里化可以缓存一部分能力,因为它返回的是一个新的函数,我们直接在返回的函数里进行操作就行。我们可以通过两个案例来说明:

三、 用函数科里化判断 vue 中标签是否是内置标签还是组件

Vue 本质上是使用 HTML 的字符串作为模板的, 将字符串的 模板 转化为 AST(抽象语法树) ,再转化为 虚拟 DOM(VNode), 最后将 虚拟 DOM 转化成 真实 DOM.

  • 模板-> AST
  • AST -> VNode
  • VNode -> 真实DOM 小插曲:上述3个过程,哪一人最消耗性能呢?答案是 模板 转化 到 AST 最消耗性能,也叫字符串解析。

问题来了,在 Vue 中, 每一个标签可以是真正的HTML标签, 也可以是自定义组件,我们怎么区分这两者?,在 Vue 源码中其实将所有可以用的 HTML 标签 都已经存起来了。

方法一:通过多对一进行判断

缺点:如果HTML 内置标签假设有 div,p,ul,li 这 4 个,我们有 6 个元素需要进行判断,就需要进行 循环遍历 24 次。

let tags = ('div,p,ul,li').split(',');
function isHtmlTag(tagName) {
  if(tags.includes(tagName.toLowerCase()))  return true;
  return false;
}
console.log(isHtmlTag('z'),  '---')   // false
console.log(isHtmlTag('div'),  '---')   // true

方法二:通过函数科里化来判断

优点:利用科里化, 只需对 set 遍历一次, 给所有内置标签加上一个属性值 true,后返回新的函数。判断我们需要判断的标签 属性值是否为 true 或 false,就行。

function makeMap(keys) {
  let set = {};
  keys.forEach(key => {set[key] = true});
  // 返回一个函数
  return function (tagName) {
    return !!set[tagName.toLowerCase()]
  }
}
let tags = ('div,p,ul,li').split(',');

let isHtmlTag = makeMap(tags);
console.log(isHtmlTag('z'),  '---')

四、虚拟 DOM 的 render 方法

思考:vue 项目中 模板 转换为 抽象语法树 需要执行几次

  • 页面一开始加载需要渲染
  • 每一个属性(响应式)数据在发生变化的时候 要渲染
  • watch, computed 等也需要渲染

1-1 中的代码 (juejin.cn/post/709446… 每次需要渲染的时候,模板就会被解析一次,这样性能是不好的, 如下

image.png

render 的作用是 将 虚拟 DOM 转化成 真正的 DOM加到页面中

  • 虚拟 DOM 可以降级理解为 AST(抽象语法树)
  • 一个项目运行的时候 模板 是不会变的,就表示 AST 也是不会变的

这样一来我们就可以把代码进行优化,将虚拟 DOM 缓存起来,生成一个函数,函数只需要传入数据就可以得到真正的 DOM.

五、偏函数和高阶函数

1. 偏函数

偏函数:一个函数原本有多个参数,先 传入一部分 参数,生成一个新的函数,由新函数来接收剩下的参数来运行得到的结构。

2. 高阶函数

高阶函数:一个函数,它的 参数是一个函数 ,该函数对参数这个函数进行加工,得到一个函数,这个加工用的函数就是高阶函数。