前端函数式演进
上QQ阅读APP看书,第一时间看更新

1.8.4 面向对象、元编程和函数式编程示例

相对于我们介绍的其他编程范式,面向对象和元编程更像是一种编程能力或思想,它们可以和其他编程范式交叉使用。

在代码清单1-9中,我们可以看到React等技术中典型的组件类。组件类是面向对象的良好载体。我们将在代码中实现一个loader(加载器),在开发时,这个loader会自动抽象出业务页面中特定前缀的常量,将其放在最外层模块(btconfigLoader.js)中统一管理。这个组件类功能展示了前端的元编程能力,其实现过程使用了一些抽象函数,这些函数可以帮助我们对过程进行抽象。

在函数式编码部分,我们可以看到代码中对过程的抽象,尤其是对if-else这种写法的函数式抽象。函数中仍然存在需要进一步解耦的内容,大家可以尝试改进代码清单中函数式的写法。

代码清单1-9 面向对象Class、元编程和函数式编程


// 1 Class - 主页面页面类
// pages/OverviewPage.js
import React from 'react'
import { OverviewMatrix, OverviewEvaluation, OverviewLink } from './overview'

const $$title1 = '关卡得分'
const $$title2 = '个人评定'

class OverviewPage extends React.Component {
  render() {
    return (
      <div className="over-view-page">
        <div>
          <span>{$$title1}</span>
          <OverviewMatrix />
        </div>
        <div>
          <span>{$$title2}</span>
          <OverviewEvaluation />
        </div>
        <div>
          <OverviewLink />
        </div>
      </div>
    )
  }
}

export default OverviewPage

// 2 元编程和函数式编程,全局变量收拢
// loader/btconfigLoader.js
const fs = require('fs');
const defineStr = 'const $$'
const costStr = '$$'
const serviceStr = 'btconfig.'
const importStr = `import btconfig from '@/btconfigLoader.js'`
const getRegWithBlank = str => str.replace(' ', '\\s')
const pr = _path => path.resolve(__dirname, '../' + _path)
const containStrFunc = (sourcestr, targetStr) => sourcestr.indexOf(targetStr) >= 0
const funcCros = (indA, funcB, funcC, funcD) => indA ? funcB() : funcC()
const replaceReturnContent = (source, defineStr, constStr) => {
  return source
         .replace(new RegExp(getRegWithBlank(defineStr),'g'), serviceStr)
         .replace(new RegExp(costStr,'g'), serviceStr)
}
const addImportStr = (importStr, content) => {
  return importStr + content
}

module.exports = function(source) {
  // 包含$$变量,则进行全局替换
  if(containStrFunc(source, defineStr)) {
    returnFileContent = replaceReturnContent(source, defineStr, constStr)
    // 如果未曾做过替换,缺少import,则把全局import写在头部
    if (!containStrFunc(returnFileContent, importStr)) {
      returnFileContent = addImportStr(importStr, returnFileContent)
    }
    return returnFileContent
  }
  // 若无$$,则不做任何动作
  return source
}

可以看到,在一个涉及不同场景的软件系统中,不同的编程范式是可以共存的。而且在这些不同的编码场景下,有针对性的编码范式能起到很好的作用。

我们示例的编码暂时还比较简单,在不同场景下还可以延伸出更深层次的功能。在后续的章节会介绍更多编码时可以改进的内容,并在第9章将完整项目展现出来。