assert 断言

本文介绍了Node.js的assert模块,详细阐述了各种断言函数的使用,包括assert.AssertionError,assert.deepEqual和assert.deepStrictEqual等,以及如何测试错误处理和异步函数的断言。此外,还解释了断言失败时的错误处理和比较规则。
摘要由CSDN通过智能技术生成

刚开始接触这块说不好自己的想法只能借用学习文档来记录我的学习过程,以后会慢慢加强的。下面是文档的内容:

assert 模块提供了断言测试的函数,用于测试不变式。

assert.AssertionError 类

Error 的一个子类,表明断言的失败。 assert 模块抛出的所有错误都是 AssertionError 类的实例。

new assert.AssertionError(options)

  • options
    • message 如果有值,则错误信息会被设为该值。
    • actual 错误实例的 actual 属性会被设为该值。用于 actual 错误输入,例如使用 assert.strictEqual()。
    • expected 错误实例的 expected 属性会被设为该值。用于 expected 错误输入,例如使用 assert.strictEqual()。
    • operator 错误实例的 operator 属性会被设为该值。用于表明比较时使用的是哪个操作(或触发错误的是哪个断言函数)。
    • stackStartFn 如果有值,则由提供的函数生成堆栈踪迹。

所有实例都包含内置的 Error 属性(message 和 name)以及:

  • actual 被设为实际值,例如使用 assert.strictEqual()。
  • expected 被设为期望值,例如使用 assert.strictEqual()。
  • generatedMessage 表明信息是否为自动生成的。
  • code 总是被设为 ERR_ASSERTION,表明错误是一个断言错误。
  • operator 被设为传入的运算符的值。
const assert = require('assert');

// 生成一个 AssertionError,用于比较错误信息:
const { message } = new assert.AssertionError({
  actual: 1,
  expected: 2,
  operator: 'strictEqual'
});

// 验证输出的错误:
try {
  assert.strictEqual(1, 2);
} catch (err) {
  assert(err instanceof assert.AssertionError);
  assert.strictEqual(err.message, message);
  assert.strictEqual(err.name, 'AssertionError [ERR_ASSERTION]');
  assert.strictEqual(err.actual, 1);
  assert.strictEqual(err.expected, 2);
  assert.strictEqual(err.code, 'ERR_ASSERTION');
  assert.strictEqual(err.operator, 'strictEqual');
  assert.strictEqual(err.generatedMessage, true);
}

assert(value[, message])

  - value <any> 要检查是否为真的值。
  - message <string> | <Error>

assert.ok() 的别名。

assert.deepEqual(actual, expected[, message])

- actual <any>
- expected <any>
- message <string> | <Error>

测试实际参数和预期参数之间的深度相等性。将原值与抽象等式比较(==).

只考虑可枚举的“自有”属性。deepequal()实现不测试对象的[[Prototype]]或可枚举的自己的符号属性。对于此类检查,请考虑使用assert.deepStrictEqual()。deepequal()可能会有令人惊讶的结果。下面的示例不会抛出AssertionError,因为RegExp对象上的属性是不可枚举的:

// WARNING: This does not throw an AssertionError!
assert.deepEqual(/a/gi, new Date());

Map和Set例外。正如预期的那样,Map和Set也会比较它们所包含的项。

“深”等式意味着子对象的可枚举的“自有”属性也被计算:

const assert = require('assert');

const obj1 = {
  a: {
    b: 1
  }
};
const obj2 = {
  a: {
    b: 2
  }
};
const obj3 = {
  a: {
    b: 1
  }
};
const obj4 = Object.create(obj1);

assert.deepEqual(obj1, obj1);
// OK

// Values of b are different:
assert.deepEqual(obj1, obj2);
// AssertionError: { a: { b: 1 } } deepEqual { a: { b: 2 } }

assert.deepEqual(obj1, obj3);
// OK

// Prototypes are ignored:
assert.deepEqual(obj1, obj4);
// AssertionError: { a: { b: 1 } } deepEqual {}

如果值不相等,将抛出AssertionError,其消息属性设置为等于消息参数的值。如果消息参数未定义,则会分配一个默认错误消息。如果消息参数是错误的实例,那么它将被抛出,而不是AssertionError。

assert.deepStrictEqual(actual, expected[, message])

- actual <any>
- expected <any>
- message <string> | <Error>

测试 actual 参数与 expected 参数是否深度相等。 深度相等意味着子对象中可枚举的自身属性也会按以下规则递归地比较。

比较的详细说明

  • 原始值运用 SameValue比较法进行比较,使用 Object.is() 函数。
  • 对象的类型标签应该相同。
  • 对象的原型使用全等运算符比较。
  • 只比较可枚举的自身属性。
  • Error 的名称与信息也会比较,即使不是可枚举的属性。
  • 可枚举的自身 Symbol 属性也会比较。
  • 对象封装器 会同时比较对象与解封装后的值。
  • Object 属性的比较是无序的。
  • Map 键名与 Set 子项的比较是无序的。
  • 当两边的值不相同或遇到循环引用时,递归会停止。
  • WeakMap 与 WeakSet 的比较不依赖于它们的值。
const assert = require('assert').strict;

// 失败,因为 1 !== '1'。
assert.deepStrictEqual({ a: 1 }, { a: '1' });
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
//   {
// -   a: 1
// +   a: '1'
//   }

// 以下对象没有自身属性。
const date = new Date();
const object = {};
const fakeDate = {};
Object.setPrototypeOf(fakeDate, Date.prototype);

// 原型不同:
assert.deepStrictEqual(object, fakeDate);
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - {}
// + Date {}

// 类型标签不同:
assert.deepStrictEqual(date, fakeDate);
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - 2018-04-26T00:49:08.604Z
// + Date {}

assert.deepStrictEqual(NaN, NaN);
// 通过,因为使用的是 SameValue 比较法。

// 解封装后的数值不同:
assert.deepStrictEqual(new Number(1), new Number(2));
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - [Number: 1]
// + [Number: 2]

assert.deepStrictEqual(new String('foo'), Object('foo'));
// 通过,因为对象与解封装后的字符串都完全相同。

assert.deepStrictEqual(-0, -0);
// 通过。

// SameValue 比较法中 0 与 -0 不同:
assert.deepStrictEqual(0, -0);
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - 0
// + -0

const symbol1 = Symbol();
const symbol2 = Symbol();
assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol1]: 1 });
// 通过,因为两边对象的 symbol 相同。
assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol2]: 1 });
// AssertionError [ERR_ASSERTION]: Input objects not identical:
// {
//   [Symbol()]: 1
// }

const weakMap1 = new WeakMap();
const weakMap2 = new WeakMap([[{}, {}]]);
const weakMap3 = new WeakMap();
weakMap3.unequal = true;

assert.deepStrictEqual(weakMap1, weakMap2);
// 通过。

// 失败,因为 weakMap3 有一个 weakMap1 没有的属性:
assert.deepStrictEqual(weakMap1, weakMap3);
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
//   WeakMap {
// -   [items unknown]
// +   [items unknown],
// +   unequal: true
//   }

如果两个值不相等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。

assert.doesNotReject(asyncFn[, error][, message])

- asyncFn <Function> | <Promise>
- error <RegExp> | <Function>
- message <string>

等待asyncFn承诺,或者,如果asyncFn是一个函数,立即调用函数并等待返回的承诺完成。然后它会检查承诺是否被拒绝。

如果asyncFn是一个函数,它会同步抛出一个错误,assert.doesNotReject()会返回一个带有该错误的拒绝承诺。如果函数不返回一个promise, assert.doesNotReject()将返回一个被拒绝的promise,并且返回一个ERR_INVALID_RETURN_VALUE错误。在这两种情况下都跳过了错误处理程序。

请注意:使用assert.doesNotReject()实际上是没有用的,因为捕获一个拒绝并再次拒绝它几乎没有什么好处。相反,考虑在特定的代码路径旁边添加一条注释,该注释不应该被拒绝,并尽可能保持错误消息的表达性。

如果指定,错误可以是类、RegExp或验证函数。有关详细信息,请参阅assert.throw()。

除了等待完成的异步性质,assert. notthrow()的行为与assert. notthrow()相同。

(async () => {
  await assert.doesNotReject(
    async () => {
      throw new TypeError('Wrong value');
    },
    SyntaxError
  );
})();
assert.doesNotReject(Promise.reject(new TypeError('Wrong value')))
  .then(() => {
    // ...
  });

assert.doesNotThrow(fn[, error][, message])

- fn <Function>
- error <RegExp> | <Function>
- message <string>

断言函数fn不会抛出错误。

请注意:使用assert.doesNotThrow()实际上是没有用的,因为捕获错误并重新抛出它没有任何好处。相反,考虑在特定的代码路径旁边添加一条注释,该注释不应该抛出错误消息,并尽可能保持错误消息的表达性。

当调用assert. notthrow()时,它将立即调用fn函数。

如果抛出的错误与错误参数指定的类型相同,则抛出AssertionError。如果错误属于另一种类型,或者错误参数未定义,则将错误传播回调用者。

如果指定,错误可以是类、RegExp或验证函数。有关详细信息,请参阅assert.throw()。

例如,下面将抛出TypeError,因为断言中没有匹配的错误类型:

assert.doesNotThrow(
  () => {
    throw new TypeError('Wrong value');
  },
  SyntaxError
);

但是,下面的消息将导致AssertionError,提示“得到不需要的异常…”

assert.doesNotThrow(
  () => {
    throw new TypeError('Wrong value');
  },
  TypeError
);

如果引发了AssertionError,并且为消息参数提供了一个值,那么将向AssertionError消息追加消息的值:

assert.doesNotThrow(
  () => {
    throw new TypeError('Wrong value');
  },
  /Wrong value/,
  'Whoops'
);
// Throws: AssertionError: Got unwanted exception: Whoops

assert.equal(actual, expected[, message])

- actual <any>
- expected <any>
- message <string> | <Error>

使用抽象平等比较(==)测试实际参数和预期参数之间的浅层强制平等。

const assert = require('assert');

assert.equal(1, 1);
// OK, 1 == 1
assert.equal(1, '1');
// OK, 1 == '1'

assert.equal(1, 2);
// AssertionError: 1 == 2
assert.equal({ a: { b: 1 } }, { a: { b: 1 } });
// AssertionError: { a: { b: 1 } } == { a: { b: 1 } }

如果值不相等,将抛出AssertionError,其消息属性设置为等于消息参数的值。如果消息参数未定义,则会分配一个默认错误消息。如果消息参数是错误的实例,那么它将被抛出,而不是AssertionError。

assert.fail([message])

- message <string> | <Error> 默认为 'Failed'。

抛出 AssertionError,并带上提供的错误信息或默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。

const assert = require('assert').strict;

assert.fail();
// 抛出 AssertionError [ERR_ASSERTION]: Failed

assert.fail('失败');
// 抛出 AssertionError [ERR_ASSERTION]: 失败

assert.fail(new TypeError('失败'));
// 抛出 TypeError: 失败

使用 assert.fail() 并带上多个参数的方法已被废弃。

assert.fail(actual, expected[, message[, operator[, stackStartFn]]])

- actual <any>
- expected <any>
- message <string> | <Error>
- operator <string> Default: '!='
- stackStartFn <Function> Default: assert.fail

如果消息是false,则将错误消息设置为实际值和预期值,由提供的操作符分隔。如果只提供了两个实际的和预期的参数,操作符将默认为’!=’。如果消息作为第三个参数提供,它将用作错误消息,其他参数将作为抛出对象上的属性存储。如果提供了stackStartFn,那么该函数上面的所有堆栈帧都将从stacktrace中删除。如果没有提供参数,将使用默认消息Failed。

const assert = require('assert').strict;

assert.fail('a', 'b');
// AssertionError [ERR_ASSERTION]: 'a' != 'b'

assert.fail(1, 2, undefined, '>');
// AssertionError [ERR_ASSERTION]: 1 > 2

assert.fail(1, 2, 'fail');
// AssertionError [ERR_ASSERTION]: fail

assert.fail(1, 2, 'whoops', '>');
// AssertionError [ERR_ASSERTION]: whoops

assert.fail(1, 2, new TypeError('need array'));
// TypeError: need array

在最后三种情况下,实际的、预期的和操作符对错误消息没有影响。

例如使用stackStartFn截断异常的stacktrace:

function suppressFrame() {
  assert.fail('a', 'b', undefined, '!==', suppressFrame);
}
suppressFrame();
// AssertionError [ERR_ASSERTION]: 'a' !== 'b'
//     at repl:1:1
//     at ContextifyScript.Script.runInThisContext (vm.js:44:33)
//     ...

assert.ifError(value)

- value <any>

如果 value 不为 undefined 或 null,则抛出 value。 可用于测试回调函数的 error 参数。 堆栈踪迹会包含传入 ifError() 的错误的所有帧,包括潜在的 ifError() 自身新增的帧。
例子:

const assert = require('assert').strict;

assert.ifError(null);
// 通过。
assert.ifError(0);
// 抛出 AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 0
assert.ifError('错误信息');
// 抛出 AssertionError [ERR_ASSERTION]: ifError got unwanted exception: '错误信息'
assert.ifError(new Error());
// 抛出 AssertionError [ERR_ASSERTION]: ifError got unwanted exception: Error

// 添加一些错误帧。
let err;
(function errorFrame() {
  err = new Error('错误信息');
})();

(function ifErrorFrame() {
  assert.ifError(err);
})();
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 错误信息
//     at ifErrorFrame
//     at errorFrame

assert.notDeepEqual(actual, expected[, message])

- actual <any>
- expected <any>
- message <string> | <Error>

测试任何深度的不等式。相反assert.deepEqual()。

const assert = require('assert');

const obj1 = {
  a: {
    b: 1
  }
};
const obj2 = {
  a: {
    b: 2
  }
};
const obj3 = {
  a: {
    b: 1
  }
};
const obj4 = Object.create(obj1);

assert.notDeepEqual(obj1, obj1);
// AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } }

assert.notDeepEqual(obj1, obj2);
// OK

assert.notDeepEqual(obj1, obj3);
// AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } }

assert.notDeepEqual(obj1, obj4);
// OK

如果值完全相等,将抛出AssertionError,其消息属性设置为等于消息参数的值。如果消息参数未定义,则会分配一个默认错误消息。如果消息参数是错误的实例,那么它将被抛出,而不是AssertionError。

assert.notDeepStrictEqual(actual, expected[, message])

- actual <any>
- expected <any>
- message <string> | <Error>

测试 actual 参数与 expected 参数是否不深度全等。 与 assert.deepStrictEqual() 相反。

const assert = require('assert').strict;

assert.notDeepStrictEqual({ a: 1 }, { a: '1' });
// 测试通过。

如果两个值深度全等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。

assert.notEqual(actual, expected[, message])

- actual <any>
- expected <any>
- message <string> | <Error>
const assert = require('assert');

assert.notEqual(1, 2);
// OK

assert.notEqual(1, 1);
// AssertionError: 1 != 1

assert.notEqual(1, '1');
// AssertionError: 1 != '1'

如果值相等,将抛出AssertionError,其消息属性设置为等于消息参数的值。如果消息参数未定义,则会分配一个默认错误消息。如果消息参数是错误的实例,那么它将被抛出,而不是AssertionError。

assert.notStrictEqual(actual, expected[, message])

- actual <any>
- expected <any>
- message <string> | <Error>

使用 SameValue比较法测试 actual 参数与 expected 参数是否不全等。

const assert = require('assert').strict;

assert.notStrictEqual(1, 2);
// 测试通过。

assert.notStrictEqual(1, 1);
// 抛出 AssertionError [ERR_ASSERTION]: Identical input passed to notStrictEqual: 1

assert.notStrictEqual(1, '1');
// 测试通过。

如果两个值全等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。

assert.ok(value[, message])

- value <any>
- message <string> | <Error>

测试 value 是否为真值。 相当于 assert.equal(!!value, true, message)。

如果 value 不为真值,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。 如果没有传入参数,则 message 会被设为字符串 'No value argument passed to assert.ok()

const assert = require('assert').strict;

assert.ok(true);
// 测试通过。
assert.ok(1);
// 测试通过。

assert.ok();
// 抛出 AssertionError: No value argument passed to `assert.ok()`

assert.ok(false, '不是真值');
// 抛出 AssertionError: 不是真值

// 在 repl 中:
assert.ok(typeof 123 === 'string');
// 抛出 AssertionError: false == true

// 在文件中(例如 test.js):
assert.ok(typeof 123 === 'string');
// 抛出 AssertionError: The expression evaluated to a falsy value:
//
//   assert.ok(typeof 123 === 'string')
assert.ok(false);
// 抛出 AssertionError: The expression evaluated to a falsy value:
//
//   assert.ok(false)

assert.ok(0);
// 抛出 AssertionError: The expression evaluated to a falsy value:
//
//   assert.ok(0)

// 等同于 `assert()`:
assert(0);
// 抛出 AssertionError: The expression evaluated to a falsy value:
//
//   assert(0)

assert.rejects(asyncFn[, error][, message])

- asyncFn <Function> | <Promise>
- error <RegExp> | <Function> | <Object> | <Error>
- message <string>

等待asyncFn承诺,或者,如果asyncFn是一个函数,立即调用函数并等待返回的承诺完成。然后它会检查承诺是否被拒绝。

如果asyncFn是一个函数,它同步抛出一个错误,assert.reject()会返回一个带有该错误的拒绝承诺。如果函数不返回一个promise, assert.reject()将返回一个拒绝的promise,并且返回一个ERR_INVALID_RETURN_VALUE错误。在这两种情况下都跳过了错误处理程序。

除了等待完成的异步性质之外,assert.throw()的行为也一样。

如果指定,错误可以是类、RegExp、验证函数、测试每个属性的对象或测试每个属性的错误实例(包括不可枚举的消息和名称属性)。

如果指定了,如果asyncFn拒绝,消息将是AssertionError提供的消息。

(async () => {
  await assert.rejects(
    async () => {
      throw new TypeError('Wrong value');
    },
    {
      name: 'TypeError',
      message: 'Wrong value'
    }
  );
})();
assert.rejects(
  Promise.reject(new Error('Wrong value')),
  Error
).then(() => {
  // ...
});

注意,错误不能是字符串。如果提供了一个字符串作为第二个参数,则假定忽略了错误,该字符串将被用于消息。这会导致容易忽略的错误。如果考虑使用字符串作为第二个参数,请仔细阅读assert.throw()中的示例。

assert.strictEqual(actual, expected[, message])

- actual <any>
- expected <any>
- message <string> | <Error>

使用 SameValue比较法测试 actual 参数与 expected 参数是否全等。

const assert = require('assert').strict;

assert.strictEqual(1, 2);
// 抛出 AssertionError [ERR_ASSERTION]: Input A expected to strictly equal input B:
// + expected - actual
// - 1
// + 2

assert.strictEqual(1, 1);
// 测试通过。

assert.strictEqual(1, '1');
// 抛出 AssertionError [ERR_ASSERTION]: Input A expected to strictly equal input B:
// + expected - actual
// - 1
// + '1'

如果两个值不全等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。

assert.throws(fn[, error][, message])

- fn <Function>
- error <RegExp> | <Function> | <Object> | <Error>
- message <string>

期望函数fn抛出一个错误。

如果指定,错误可以是类、RegExp、验证函数、验证对象,其中每个属性都将被测试为严格的深度相等,或者错误实例,其中每个属性都将被测试为严格的深度相等,包括不可枚举的消息和名称属性。在使用对象时,在对字符串属性进行验证时,也可以使用正则表达式。下面是一些例子。

如果指定,如果fn调用未能抛出或错误验证失败,则会将消息追加到AssertionError提供的消息中。

自定义验证对象/错误实例:

const err = new TypeError('Wrong value');
err.code = 404;
err.foo = 'bar';
err.info = {
  nested: true,
  baz: 'text'
};
err.reg = /abc/i;

assert.throws(
  () => {
    throw err;
  },
  {
    name: 'TypeError',
    message: 'Wrong value',
    info: {
      nested: true,
      baz: 'text'
    }
    // Note that only properties on the validation object will be tested for.
    // Using nested objects requires all properties to be present. Otherwise
    // the validation is going to fail.
  }
);

// Using regular expressions to validate error properties:
assert.throws(
  () => {
    throw err;
  },
  {
    // The `name` and `message` properties are strings and using regular
    // expressions on those will match against the string. If they fail, an
    // error is thrown.
    name: /^TypeError$/,
    message: /Wrong/,
    foo: 'bar',
    info: {
      nested: true,
      // It is not possible to use regular expressions for nested properties!
      baz: 'text'
    },
    // The `reg` property contains a regular expression and only if the
    // validation object contains an identical regular expression, it is going
    // to pass.
    reg: /abc/i
  }
);

// Fails due to the different `message` and `name` properties:
assert.throws(
  () => {
    const otherErr = new Error('Not found');
    otherErr.code = 404;
    throw otherErr;
  },
  err // This tests for `message`, `name` and `code`.
);

Validate instanceof using constructor:

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  Error
);

使用RegExp验证错误消息:

使用正则表达式在错误对象上运行. tostring,因此还将包含错误名称。

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  /^Error: Wrong value$/
);

自定义错误验证:

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  function(err) {
    if ((err instanceof Error) && /value/.test(err)) {
      return true;
    }
  },
  'unexpected error'
);

注意,错误不能是字符串。如果提供了一个字符串作为第二个参数,则假定忽略了错误,该字符串将被用于消息。这会导致容易忽略的错误。使用与抛出错误消息相同的消息将导致err_ous_argument错误。如果考虑使用字符串作为第二个参数,请仔细阅读下面的示例:

function throwingFirst() {
  throw new Error('First');
}
function throwingSecond() {
  throw new Error('Second');
}
function notThrowing() {}

// The second argument is a string and the input function threw an Error.
// The first case will not throw as it does not match for the error message
// thrown by the input function!
assert.throws(throwingFirst, 'Second');
// In the next example the message has no benefit over the message from the
// error and since it is not clear if the user intended to actually match
// against the error message, Node.js thrown an `ERR_AMBIGUOUS_ARGUMENT` error.
assert.throws(throwingSecond, 'Second');
// Throws an error:
// TypeError [ERR_AMBIGUOUS_ARGUMENT]

// The string is only used (as message) in case the function does not throw:
assert.throws(notThrowing, 'Second');
// AssertionError [ERR_ASSERTION]: Missing expected exception: Second

// If it was intended to match for the error message do this instead:
assert.throws(throwingSecond, /Second$/);
// Does not throw because the error messages match.
assert.throws(throwingFirst, /Second$/);
// Throws an error:
// Error: First
//     at throwingFirst (repl:2:9)

由于符号混乱,建议不要使用字符串作为第二个参数。这可能会导致难以发现的错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值