dynamic noSuchMethod(Invocation invocation)

当一个不存在的函数或成员变量被访问时,该函数被调用。

类可以重写noSuchMethod来提供自定义行为。

如果返回一个值,那么这个值将成为原始调用的结果。

默认的行为是抛出一个NoSuchMethodError

Source

noSuchMethod(Invocation invocation) {
  throwError() {
    super.noSuchMethod(invocation);
  }

  String name = _stripReservedNamePrefix(
      mirrors.MirrorSystem.getName(invocation.memberName));
  argsSafeForTypedInterop(invocation.positionalArguments);
  if (invocation.isGetter) {
    if (CHECK_JS_INVOCATIONS) {
      var matches = _allowedGetters[invocation.memberName];
      if (matches == null &&
          !_allowedMethods.containsKey(invocation.memberName)) {
        throwError();
      }
      var ret = _operator_getter(name);
      if (matches != null) return ret;
      if (ret is Function ||
          (ret is JsFunction /* shouldn't be needed in the future*/) &&
              _allowedMethods.containsKey(invocation.memberName))
        return ret; // Warning: we have not bound "this"... we could type check on the Function but that is of little value in Dart.
      throwError();
    } else {
      // TODO(jacobr): should we throw if the JavaScript object doesn't have the property?
      return _operator_getter(name);
    }
  } else if (invocation.isSetter) {
    if (CHECK_JS_INVOCATIONS) {
      var matches = _allowedSetters[invocation.memberName];
      if (matches == null || !matches.checkInvocation(invocation))
        throwError();
    }
    assert(name.endsWith("="));
    name = name.substring(0, name.length - 1);
    return _operator_setter(name, invocation.positionalArguments.first);
  } else {
    // TODO(jacobr): also allow calling getters that look like functions.
    var matches;
    if (CHECK_JS_INVOCATIONS) {
      matches = _allowedMethods[invocation.memberName];
      if (matches == null || !matches.checkInvocation(invocation))
        throwError();
    }
    var ret = _callMethod(name, _buildArgs(invocation));
    if (CHECK_JS_INVOCATIONS) {
      if (!matches._checkReturnType(ret)) {
        html.window.console.error("Return value for method: ${name} is "
            "${ret.runtimeType} which is inconsistent with all typed "
            "JS interop definitions for method ${name}.");
      }
    }
    return ret;
  }
}