extend = function (opts) {

      var nativeClass = globalContext[name], nativeProto = nativeClass.prototype;
      var staticMethods = {}, instanceMethods = {}, methodsByName;

      function objectRestricted(name, target) {
        return isObject && target === nativeProto &&
               (!allowObjectPrototype || name === 'get' || name === 'set');
      }

      function arrayOptionExists(field, val) {
        var arr = opts[field];
        if (arr) {
          for (var i = 0, el; el = arr[i]; i++) {
            if (el === val) {
              return true;
            }
          }
        }
        return false;
      }

      function arrayOptionExcludes(field, val) {
        return opts[field] && !arrayOptionExists(field, val);
      }

      function disallowedByFlags(methodName, target, flags) {
        // Disallowing methods by flag currently only applies if methods already
        // exist to avoid enhancing native methods, as aliases should still be
        // extended (i.e. Array#all should still be extended even if Array#every
        // is being disallowed by a flag).
        if (!target[methodName] || !flags) {
          return false;
        }
        for (var i = 0; i < flags.length; i++) {
          if (opts[flags[i]] === false) {
            return true;
          }
        }
      }

      function namespaceIsExcepted() {
        return arrayOptionExists('except', nativeClass) ||
               arrayOptionExcludes('namespaces', nativeClass);
      }

      function methodIsExcepted(methodName) {
        return arrayOptionExists('except', methodName);
      }

      function canExtend(methodName, method, target) {
        return !objectRestricted(methodName, target) &&
               !disallowedByFlags(methodName, target, method.flags) &&
               !methodIsExcepted(methodName);
      }

      opts = opts || {};
      methodsByName = opts.methods;

      if (namespaceIsExcepted()) {
        return;
      } else if (isObject && typeof opts.objectPrototype === 'boolean') {
        // Store "objectPrototype" flag for future reference.
        allowObjectPrototype = opts.objectPrototype;
      }

      forEachProperty(methodsByName || sugarNamespace, function(method, methodName) {
        if (methodsByName) {
          // If we have method names passed in an array,
          // then we need to flip the key and value here
          // and find the method in the Sugar namespace.
          methodName = method;
          method = sugarNamespace[methodName];
        }
        if (hasOwn(method, 'instance') && canExtend(methodName, method, nativeProto)) {
          instanceMethods[methodName] = method.instance;
        }
        if(hasOwn(method, 'static') && canExtend(methodName, method, nativeClass)) {
          staticMethods[methodName] = method;
        }
      });

      // Accessing the extend target each time instead of holding a reference as
      // it may have been overwritten (for example Date by Sinon). Also need to
      // access through the global to allow extension of user-defined namespaces.
      extendNative(nativeClass, staticMethods);
      extendNative(nativeProto, instanceMethods);

      if (!methodsByName) {
        // If there are no method names passed, then
        // all methods in the namespace will be extended
        // to the native. This includes all future defined
        // methods, so add a flag here to check later.
        setProperty(sugarNamespace, 'active', true);
      }
      return sugarNamespace;
    }
@method extend([opts])
@returns Sugar
@namespace Sugar
@short Extends Sugar defined methods onto natives.
@extra This method can be called on individual namespaces like
       `Sugar.Array` or on the `Sugar` global itself, in which case
       [opts] will be forwarded to each `extend` call. For more,
       see `extending`.

@options

  methods           An array of method names to explicitly extend.

  except            An array of method names or global namespaces (`Array`,
                    `String`) to explicitly exclude. Namespaces should be the
                    actual global objects, not strings.

  namespaces        An array of global namespaces (`Array`, `String`) to
                    explicitly extend. Namespaces should be the actual
                    global objects, not strings.

  enhance           A shortcut to disallow all "enhance" flags at once
                    (flags listed below). For more, see `enhanced methods`.
                    Default is `true`.

  enhanceString     A boolean allowing String enhancements. Default is `true`.

  enhanceArray      A boolean allowing Array enhancements. Default is `true`.

  objectPrototype   A boolean allowing Sugar to extend Object.prototype
                    with instance methods. This option is off by default
                    and should generally not be used except with caution.
                    For more, see `object methods`.

@example

  Sugar.Array.extend();
  Sugar.extend();

@option {Array<string>} [methods]
@option {Array<string|NativeConstructor>} [except]
@option {Array<NativeConstructor>} [namespaces]
@option {boolean} [enhance]
@option {boolean} [enhanceString]
@option {boolean} [enhanceArray]
@option {boolean} [objectPrototype]
@param {ExtendOptions} [opts]

**
@method extend([opts])
@returns SugarNamespace
@namespace SugarNamespace
@short Extends Sugar defined methods for a specific namespace onto natives.
@param {ExtendOptions} [opts]

*