今天看到了一个断言库power-assertAPI 兼容 assert但是对于

assert(this.ary.indexOf(zero) === two)

会输出

  1) Array #indexOf() should return index when the value is present:
     AssertionError: # path/to/test/mocha_node.js:10

  assert(this.ary.indexOf(zero) === two)
              |   |       |     |   |
              |   |       |     |   2
              |   -1      0     false
              [1,2,3]

  [number] two
  => 2
  [number] this.ary.indexOf(zero)
  => -1

可以看到它用最简单的表达式来断言但是当表达式不成立时输出的内容却非常详细

再来一个输出的例子

    assert(this.types[index].name === bob.name)
                |    ||      |    |   |   |
                |    ||      |    |   |   "bob"
                |    ||      |    |   Person{name:"bob",age:5}
                |    ||      |    false
                |    |11     "alice"
                |    Person{name:"alice",age:3}
                ["string",98.6,true,false,null,undefined,#Array#,#Object#,NaN,Infinity,/^not/,#Person#]

    --- [string] bob.name
    +++ [string] this.types[index].name
    @@ -1,3 +1,5 @@
    -bob
    +alice

它把每一级的值都直观地输出了出来

没错它并不是一个级别的东西JavaScript 语言本身的能力还不足以实现这样的库确切地说这是一个 transpilerespower对测试文件 example_test.js

var assert = require('power-assert');
var truthy = 'true';
var falsy = 'false';
assert(falsy);
assert.equal(truthy, falsy);

它会转译成

var _PowerAssertRecorder1 = function () {
    function PowerAssertRecorder() {
        this.captured = [];
    }
    PowerAssertRecorder.prototype._capt = function _capt(value, espath) {
        this.captured.push({
            value: value,
            espath: espath
        });
        return value;
    };
    PowerAssertRecorder.prototype._expr = function _expr(value, source) {
        var capturedValues = this.captured;
        this.captured = [];
        return {
            powerAssertContext: {
                value: value,
                events: capturedValues
            },
            source: source
        };
    };
    return PowerAssertRecorder;
}();
var _rec1 = new _PowerAssertRecorder1();
var _rec2 = new _PowerAssertRecorder1();
var _rec3 = new _PowerAssertRecorder1();
var assert = require('power-assert');
var truthy = 'true';
var falsy = 'false';
assert(_rec1._expr(_rec1._capt(falsy, 'arguments/0'), {
    content: 'assert(falsy)',
    filepath: 'example_test.js',
    line: 4
}));
assert.equal(_rec2._expr(_rec2._capt(truthy, 'arguments/0'), {
    content: 'assert.equal(truthy, falsy)',
    filepath: 'example_test.js',
    line: 5
}), _rec3._expr(_rec3._capt(falsy, 'arguments/1'), {
    content: 'assert.equal(truthy, falsy)',
    filepath: 'example_test.js',
    line: 5
}));

写编译器不意味着创造一种新的语言近几年的前端呈现出一种编译器爆发的状态从最早的 CoffeeScriptWind.js到后来的 Babelespower……编译器做的事情越来越简单CoffeeScript 尚且算是一门新语言其他的就只是 JavaScript => JavaScript 的编译器了

其实对于 JavaScript 来说更需要各种各样的 transpilerC 有 macroC++ 有 template赋予了它们在编译期间的代码生成能力也就是所说的元编程JavaScript 里实现元编程却有一定的门槛而且由于是在运行时实现的因此会存在一些性能上的问题和局限性