博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
javascript 元编程之 method_missing
阅读量:5331 次
发布时间:2019-06-14

本文共 2975 字,大约阅读时间需要 9 分钟。

javascript 元编程之 method_missing

引言

要说元编程 ruby 中技巧太多了,今天来写的这个技术也来自于 ruby 中的灵感。

method_missing 这个在 ruby 中对象调用方法如果没有调到就会去调用这个方法。

这个功能在 javascript 中怎么实现,现在 proxy 出现了,这个就有思路了。

实现

class Base {  constructor () {    return new Proxy(this, {      get (target, property) {        if (Reflect.has(target, property)) {          return Reflect.get(target, property)        } else {          return function () {            if (target.method_missing) {              return target.method_missing(property, ...arguments)            } else {              throw new ReferenceError('Property "' + property + '" does not exist.')            }          }        }      }    })  }}

代码解释一下, 用了 class, Proxy 的功能。

怎样使用呢?

我说一下应用场景,在前端单页面中,有很多的 ajax 接口,如果你想使用一般情况下会怎么做呢?

会先把网络库(jquery, axios) 封一层变成 http ,然后再把请求分一层,变成 request,最后对每个接口封一层,把调用方法变成一个一个的方法,放到一个文件夹中管理 api,然后在别的地方引用。

这样当然能工作。问题在于接口信息太冗余,接口的信息放在三个地方,url 中,参数中,方法名,如果有一个要改,可能三个地方都要改。

而且是要对每个函数都要做一遍这个工作。

下面举例:

// http 方法import $ from 'jquery'window.jQuery = $$.ajaxSetup({  cache: false,  dataType: 'json'})// request 方法export function request (url, setting) {  return new Promise((resolve, reject) => {    $.ajax(url, setting)      .then(resolve)      .fail(reject)  })}export function get (url, params) {  return request(url, {    method: 'GET',    data: params  })}export function post (url, params) {  return request(url, {    method: 'POST',    data: params  })}// 具体的方法import { post } from '@/lib/http'export function getPermission (params = {}) {  return post('/passport/permission', params)}

我们可以看到具体的方法中,函数名和 url 其实都在表达一个意思,而且如果再来接口我还要这么干。

如果20多个接口,都是这种重复代码,不应该这么干。

实现

怎么做?

上面写的 method_missing 方法上场了,我们不封方法了,直接写函数,然后委托 method_missing 方法进行统一的调用,让我们从重复的封方法中解脱出来,干点别的什么事。

import Base from './base'import { request } from './http'import * as _ from 'lodash'let METHOD = {  GET: ['get', 'show'],  POST: ['post', 'update', 'change', 'create', 'delete', 'remove']}class ApiService extends Base {  constructor () {    super()    this.baseURL = '/api/web'  }  method_missing (property, ...args) {    let [url, setting] = args    if (_.isObject(url)) {      setting = {        data: url      }      // 这里通过方法名生成 url      const url_parts = property.split('_')      const method = url_parts[0].toLowerCase()      if (METHOD.GET.includes(method)) {        setting.method = 'GET'        url_parts.shift()      } else if (METHOD.POST.includes(method)) {        setting.method = 'POST'        url_parts.shift()      } else {        setting.method = 'GET'      }      url = '/' + url_parts.join('/')    }    return request(this.baseURL + url, setting)  }}export default new ApiService()// 执行代码import apiService from './api-service'// 调用,神奇的代码apiService.get_passport_permission({})

从执行代码来看,我并没有定义这个方法,这个方法会落到 apiserver 中的 method_missing 中去。

拿到方法名和参数列表,我就能干事情,跟据方法名去生成 url,然后参数加上,就能发请求了。

结论

这个方法在代码上如果你接口特别多的话,可以节省太多的样板代码,而且是越是通用的代码,越好,如果有特例的代码,可以加到实现 method_missing 的类中。

这样通用的代码和特例的代码都能兼顾,当然兼容性还是要考虑的。

转载于:https://www.cnblogs.com/htoooth/p/11367829.html

你可能感兴趣的文章
js输出
查看>>
set,env,export,set -x,set -e;
查看>>
H5多文本换行
查看>>
HAL层三类函数及其作用
查看>>
Odoo 去掉 恼人的 "上午"和"下午"
查看>>
web@h,c小总结
查看>>
java编程思想笔记(一)——面向对象导论
查看>>
Data Structure 基本概念
查看>>
Ubuntu改坏sudoers后无法使用sudo的解决办法
查看>>
NEYC 2017 游记
查看>>
【BZOJ 3669】 [Noi2014]魔法森林 LCT维护动态最小生成树
查看>>
[搬运] 写给 C# 开发人员的函数式编程
查看>>
Shiro权限控制框架
查看>>
vsftpd虚拟用户【公司系统部分享】
查看>>
盒子box在网页中居中的方法
查看>>
Python之旅Day14 JQuery部分
查看>>
core--线程池
查看>>
redux-effect
查看>>
Swift和OC混编
查看>>
Android轻量级的开源缓存框架ASimpleCache
查看>>