partialFn = function() {
        var argIndex = 0, applyArgs = [], self = this, lock = _lock(partialFn), result, i;
        for (i = 0; i < curriedLen; i++) {
          var arg = curriedArgs[i];
          if (isDefined(arg)) {
            applyArgs[i] = arg;
          } else {
            applyArgs[i] = arguments[argIndex++];
          }
        }
        for (i = argIndex; i < arguments.length; i++) {
          applyArgs.push(arguments[i]);
        }
        if (lock === null) {
          lock = curriedLen;
        }
        if (isNumber(lock)) {
          applyArgs.length = min(applyArgs.length, lock);
        }
        // If the bound "this" object is an instance of the partialed
        // function, then "new" was used, so preserve the prototype
        // so that constructor functions can also be partialed.
        if (self instanceof partialFn) {
          self = createInstanceFromPrototype(fn.prototype);
          result = fn.apply(self, applyArgs);
          // An explicit return value is allowed from constructors
          // as long as they are of "object" type, so return the
          // correct result here accordingly.
          return isObjectType(result) ? result : self;
        }
        return fn.apply(self, applyArgs);
      }
@method partial([arg1], [arg2], ...)
@returns Function
@short Returns a new version of the function which has part of its arguments
       pre-emptively filled in, also known as "currying".
@extra `undefined` can be passed as any argument, and is a placeholder that
       will be replaced with arguments passed when the function is executed.
       This allows currying of arguments even when they occur toward the end
       of an argument list (the example demonstrates this more clearly).

@example

  logArgs.partial(undefined, 'b')('a') -> logs a, b

@param {any} [arg1]
@param {any} [arg2]

*