8

我开始使用 facebook javscript SDK,在阅读源代码时发现了一件有趣的事情。

代码示例如下:

/**
 * Annotates a function with a meta object
 */
function annotate(fn, meta) {
    meta.superClass = fn.__superConstructor__;
    fn.__TCmeta = meta;
    return fn;
}

// export to global
__w = annotate;

/**
 * when using the annotate function
 */
function sprintf(format) {
   // function body
}
__w(sprintf, {"signature":"function(string)"});   // <-- what is the purpose of doing this?

所以,我的问题是它是做什么用的?这样做有什么好处

仅供参考,完整的源代码在这里,你可以看到很多 annotate() 正在被使用

http://connect.facebook.net/en_US/all/debug.js

4

1 回答 1

3

它似乎是一个本土的强类型设置:

/**
 * A recursive descent analyzer which takes a value and a typehint, validating
 * whether or not the value matches the typehint.
 * The function will call it self as long as both the value and the typehint
 * yields a nested component. This means that we will never recurse deeper
 * than needed, and also that we automatically get support for
 *   > equals([], 'array<string>') // true
 *   > equals(['string'], 'array') // true
 */
function equals(value, node) {
  var type = typeof value;
  var subType;
  var nextNode;
  var nextValue;

  //: Nullable types are delimited with a leading ?
  //: ?string, ?boolean, etc.
  var nullable = /^\?/.test(node);
  if (nullable) {
    node = node.substring(1);
  }

//: snip ...

switch (type) {
  // start by testing the most common types
  case 'boolean':
  case 'number':
  case 'string':
  case 'undefined':
    break;
  default:
      //: snip ...
      // let functions with signatures also match 'function'
      type = value.__TCmeta && node !== 'function'
        ? value.__TCmeta.signature
        : 'function';
    } else if (type === 'object' || type === 'function') {
      // HTMLObjectElements has a typeof function in FF
      var constructor = value.constructor;
      if (constructor && constructor.__TCmeta) {
        // The value is a custom type
        //: snip ...
          while (constructor && constructor.__TCmeta) {
            if (constructor.__TCmeta.type == node) {
              type = node;
              break;
            }
            constructor = constructor.__TCmeta.superClass;
          }
        //: snip ...
        }
      }
    }
}

if (nullable && /undefined|null/.test(type)) {
  return true;
}

if (type in typeInterfaces) {
  var interfaces = typeInterfaces[type], i = interfaces.length;
  while (i--) {
    if (interfaces[i] === node) {
      type = node;
      break;
    }
  }
}

currentType.push(type);
return nextValue && nextNode
  ? node === type && equals(nextValue, nextNode)
  : subType && nextNode
    ? node === type && subType === nextNode
    : node === type;
}

 

/**
 * Given a value and a typehint (can be a union type), this will return
 * whether or not the passed in value matches the typehint.
 */
function matches(value, node) {
  var nodes = node.split('|'), i = nodes.length;
  while (i--) {
    currentType = [];
    if (equals(value, nodes[i])) {
      return true;
    }
  }
  return false;
}

他们使用该annotate函数的原因是允许对自定义类型和函数签名进行类型提示。没有annotate你只能做matches(someVar, "function")annotate你可以做matches(someVar, "function(string, ?int)|function(string)")并且只接受接受字符串和可为空的函数integer或只接受字符串的函数。

于 2013-10-03T03:16:02.517 回答