用于替换javascript关键字的预处理器

时间:2014-07-16 15:04:16

标签: javascript

我使用的是Angular version of the $q library,但这也与original q library相关。

用法示例:

$q
  .when(someFunction)
  .then(function(){
    // ..
  })
  .catch(function(){
    // ..
  })
  .finally(function(){
    // ..
  });

不幸的是,某些功能名称(例如finally)与javascript关键字冲突 来自Angular参考:

“因为最终是JavaScript中的保留字,并且不支持保留关键字作为ES3的属性名称,所以您需要调用promise['finally'](callback) 使您的代码与IE8和Android 2.x兼容。“

官方标准ECMA-262,http://www.ecma-international.org/publications/standards/Ecma-262.htm,提供:

  

7.6.1.1关键字

     

以下令牌是ECMAScript关键字,可能用作   ECMAScript程序中的标识符。

break           do              instanceof      typeof  
case            else            new             var 
catch           finally         return          void 
continue        for             switch          while 
debugger        function        this            with 
default         if              throw            
delete          in              try

这意味着必须将第一个示例更改为以下代码才能使其与IE8一起使用:

$q
  .when(someFunction)
  .then(function(){
    // ..
  })
  ['catch'](function(){
    // ..
  })
  ['finally'](function(){
    // ..
  });

由于这段代码难以维护,我正在寻找一个javascript预处理器(可能是一个繁琐的任务),它将第一个例子变成IE8兼容版本。

是否有这样的预处理器?

1 个答案:

答案 0 :(得分:8)

几个月前,你友好的邻居Stef Panner为此创造了这样一个工具。它被称为es3-safe-recast。它还有一个grunt task

让我们来看看它的作用。首先,它需要用于JS语法树分析的Esprima包,并在它之上重新构建为这些转换而构建的:

'use strict';
var esprima = require('esprima');
var recast = require('recast');
var Visitor = recast.Visitor;
var types = recast.types;
var namedTypes = types.namedTypes;
var builders = types.builders;

然后它包含所有标识符的大地图 - 就像您的列表一样:

identifierToLiteral.finally = true; // here is `finally` for example

以下是它如何解析树并将其替换为访问者:

var ES6Safe = Visitor.extend({
  visitProperty: function(node) { // go through all properties
    // check if need to replace name with literal
    if (namedTypes.Identifier.check(node.key) && identifierToLiteral[node.key.name]) {
      node.key = builders.literal(node.key.name);
    }

    return this.genericVisit(node);
  },

  visitMemberExpression: function(node) { // and all member expressions
    var property = node.property;
    var newNode;
    // check if need to replace name with literal
    if (namedTypes.Identifier.check(property) && identifierToLiteral[property.name]) {
      newNode = builders.memberExpression(node.object, builders.literal(property.name), true);
    } else {
      newNode = node;
    }
    return this.genericVisit(newNode);
  }
});

最后,它通过重铸运行代码:

ast = recast.parse(source, { esprima: esprima } );
new ES6Safe().visit(ast);
code = recast.print(ast).code;

制作上述代码的安全版本。