ihtml5 / blog

个人博客 源码阅读*前端实践 My Blog
MIT License
6 stars 0 forks source link

从获取函数形参谈toString用法 #61

Open ihtml5 opened 7 years ago

ihtml5 commented 7 years ago

问题

如何获取一个函数形参?我们都知道通过arguments可以获取运行时的实参值,但是形参值怎么获取,如果我们对toString的用法了解,这个问题就好解答了

toString

Function.prototype.toString里有一句话说,在一个函数上直接调用toString方法,会以字符串形式返回这个函数的源码。这里有个重要信息,通过调用toString() 方法可以反编译解析出函数源码,多么强大简单的功能。

// 撸代码
function tq(a, b, c) {}
tq.toString();
// "function tq(a, b, c) {}" 那么剩下的事情就是通过正则匹配解析出圆括号里面的内容了,简单吧

前人已经写的几种获取函数形参的方法

  1. get-parameter-names 推荐使用
    
    //https://github.com/goatslacker/get-parameter-names/blob/master/index.js
    // 看不懂正则的,可以上https://regexper.com
    var COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
    var DEFAULT_PARAMS = /=[^,]+/mg;
    var FAT_ARROWS = /=>.*$/mg;

function getParameterNames(fn) { var code = fn.toString() .replace(COMMENTS, '') .replace(FAT_ARROWS, '') .replace(DEFAULT_PARAMS, '');

var result = code.slice(code.indexOf('(') + 1, code.indexOf(')')) .match(/([^\s,]+)/g);

return result === null ? [] : result; }

module.exports = getParameterNames;

2.  **同1类似的方法**
```javascript
function getArgs(func) {
 // 先用正则匹配,取得符合参数模式的字符串.
 // 第一个分组是这个: ([^)]*) 非右括号的任意字符
 var args = func.toString().match(/function\s.*?\(([^)]*)\)/)[1];
 // 用逗号来分隔参数(arguments string).
 return args.split(",").map(function(arg) {
  // 去除注释(inline comments)以及空格
  return arg.replace(/\/\*.*\*\//, "").trim();
 }).filter(function(arg) {
  // 确保没有 undefined.
  return arg;
 });
}
  1. 知乎上贺师俊提供了一个更简单的方法
    //https://www.zhihu.com/question/28912825
    /\(\s*([\s\S]*?)\s*\)/.exec(fn)[1].split(/\s*,\s*/)

    方法一考虑到单行注释,多行注释,默认值,箭头函数多种情况,适应情况更多,推荐使用方法一

    toString其他用法

  2. Object.prototype.toString 判断变量类型,这个经常在比如jquery等各种类库中常用
    Object.prototype.toString.call(obj);
  3. Number.prototype.toString 将数字转化为字符串,比如1转化为‘1’
  4. Boolean.prototype.toString
    var b = true;
    console.log(b.toString()); // 'true'
  5. Array.prototype.toString // 行为类似于 [].join(',');
    [].toString() // ''
    [1, 2].toString() // '1,2'
  6. Symbol.prototype.toString // 行为类似于Function.prototype.toString会将Symbol函数源码解析出来