mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-01 15:57:48 +00:00
Make chaining actions deferred until value is called.
This commit is contained in:
105
lodash.js
105
lodash.js
@@ -841,7 +841,7 @@
|
||||
return value;
|
||||
}
|
||||
if (!isArray(value) && hasOwnProperty.call(value, '__wrapped__')) {
|
||||
value = value.__wrapped__;
|
||||
return new lodashWrapper(value.__wrapped__, value.__chain__, baseSlice(value.__queue__));
|
||||
}
|
||||
}
|
||||
return new lodashWrapper(value);
|
||||
@@ -853,10 +853,12 @@
|
||||
* @private
|
||||
* @param {*} value The value to wrap in a `lodash` instance.
|
||||
* @param {boolean} [chainAll=false] Enable chaining for all methods.
|
||||
* @param {Array} [queue=[]] Actions to peform to resolve the unwrapped value.
|
||||
* @returns {Object} Returns a `lodash` instance.
|
||||
*/
|
||||
function lodashWrapper(value, chainAll) {
|
||||
function lodashWrapper(value, chainAll, queue) {
|
||||
this.__chain__ = !!chainAll;
|
||||
this.__queue__ = queue || [];
|
||||
this.__wrapped__ = value;
|
||||
}
|
||||
|
||||
@@ -1875,7 +1877,7 @@
|
||||
othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
|
||||
|
||||
if (valWrapped || othWrapped) {
|
||||
return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, customizer, isWhere, stackA, stackB);
|
||||
return baseIsEqual(valWrapped ? value.value() : value, othWrapped ? other.value() : other, customizer, isWhere, stackA, stackB);
|
||||
}
|
||||
if (!isSameClass) {
|
||||
return false;
|
||||
@@ -4525,8 +4527,7 @@
|
||||
* // => { 'age': 36 }
|
||||
*/
|
||||
function wrapperChain() {
|
||||
this.__chain__ = true;
|
||||
return this;
|
||||
return chain(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4542,7 +4543,7 @@
|
||||
* // => '1,2,3'
|
||||
*/
|
||||
function wrapperToString() {
|
||||
return String(this.__wrapped__);
|
||||
return String(this.value());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4559,7 +4560,26 @@
|
||||
* // => [1, 2, 3]
|
||||
*/
|
||||
function wrapperValueOf() {
|
||||
return this.__wrapped__;
|
||||
var index = -1,
|
||||
queue = this.__queue__,
|
||||
length = queue.length,
|
||||
result = this.__wrapped__;
|
||||
|
||||
while (++index < length) {
|
||||
var data = queue[index],
|
||||
methodName = data[0];
|
||||
|
||||
if (typeof methodName == 'function') {
|
||||
result = methodName.apply(result, data[2]);
|
||||
} else {
|
||||
var args = [result],
|
||||
object = data[1];
|
||||
|
||||
push.apply(args, data[2]);
|
||||
result = object[methodName].apply(object, args);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
@@ -8936,28 +8956,25 @@
|
||||
length = methodNames.length;
|
||||
|
||||
while (++index < length) {
|
||||
var methodName = methodNames[index],
|
||||
func = object[methodName] = source[methodName];
|
||||
|
||||
var methodName = methodNames[index];
|
||||
object[methodName] = source[methodName];
|
||||
if (isFunc) {
|
||||
object.prototype[methodName] = (function(func) {
|
||||
object.prototype[methodName] = (function(methodName) {
|
||||
return function() {
|
||||
var chainAll = this.__chain__,
|
||||
value = this.__wrapped__,
|
||||
args = [value];
|
||||
if (chain || this.__chain__) {
|
||||
var queue = baseSlice(this.__queue__),
|
||||
result = object(this.__wrapped__);
|
||||
|
||||
push.apply(args, arguments);
|
||||
var result = func.apply(object, args);
|
||||
if (chain || chainAll) {
|
||||
if (value === result && isObject(result)) {
|
||||
return this;
|
||||
}
|
||||
result = new object(result);
|
||||
result.__chain__ = chainAll;
|
||||
result.__chain__ = this.__chain__;
|
||||
result.__queue__ = queue;
|
||||
queue.push([methodName, object, arguments]);
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
var args = [this.value()];
|
||||
push.apply(args, arguments);
|
||||
return object[methodName].apply(object, args);
|
||||
};
|
||||
}(func));
|
||||
}(methodName));
|
||||
}
|
||||
}
|
||||
return object;
|
||||
@@ -9515,19 +9532,13 @@
|
||||
// add functions capable of returning wrapped and unwrapped values when chaining
|
||||
lodash.sample = sample;
|
||||
|
||||
baseForOwn(lodash, function(func, methodName) {
|
||||
var callbackable = methodName != 'sample';
|
||||
if (!lodash.prototype[methodName]) {
|
||||
lodash.prototype[methodName] = function(n, guard) {
|
||||
var chainAll = this.__chain__,
|
||||
result = func(this.__wrapped__, n, guard);
|
||||
|
||||
return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
|
||||
? result
|
||||
: new lodashWrapper(result, chainAll);
|
||||
};
|
||||
lodash.prototype.sample = function(n, guard) {
|
||||
if (!this.__chain__ && (n == null || guard)) {
|
||||
return lodash.sample(this.value());
|
||||
}
|
||||
});
|
||||
this.__queue__.push(['sample', lodash, [n]]);
|
||||
return this;
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
@@ -9557,12 +9568,12 @@
|
||||
arrayEach(['join', 'pop', 'shift'], function(methodName) {
|
||||
var func = arrayProto[methodName];
|
||||
lodash.prototype[methodName] = function() {
|
||||
var chainAll = this.__chain__,
|
||||
result = func.apply(this.__wrapped__, arguments);
|
||||
|
||||
return chainAll
|
||||
? new lodashWrapper(result, chainAll)
|
||||
: result;
|
||||
if (!this.__chain__) {
|
||||
return func.apply(this.value(), arguments)
|
||||
}
|
||||
var result = new lodashWrapper(value.__wrapped__, value.__chain__, baseSlice(value.__queue__))
|
||||
result.__queue__.push([func, null, arguments]);
|
||||
return result;
|
||||
};
|
||||
});
|
||||
|
||||
@@ -9570,8 +9581,10 @@
|
||||
arrayEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
|
||||
var func = arrayProto[methodName];
|
||||
lodash.prototype[methodName] = function() {
|
||||
func.apply(this.__wrapped__, arguments);
|
||||
return this;
|
||||
var args = arguments;
|
||||
return this.tap(function(value) {
|
||||
func.apply(value, args);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
@@ -9579,7 +9592,7 @@
|
||||
arrayEach(['concat', 'splice'], function(methodName) {
|
||||
var func = arrayProto[methodName];
|
||||
lodash.prototype[methodName] = function() {
|
||||
return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
|
||||
return new lodashWrapper(func.apply(this.value(), arguments), this.__chain__);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -9592,7 +9605,7 @@
|
||||
|
||||
lodash.prototype[methodName] = function() {
|
||||
var chainAll = this.__chain__,
|
||||
value = this.__wrapped__,
|
||||
value = this.value(),
|
||||
result = func.apply(value, arguments);
|
||||
|
||||
if (value.length === 0) {
|
||||
|
||||
36
test/test.js
36
test/test.js
@@ -754,7 +754,7 @@
|
||||
if (lodashBizarro) {
|
||||
var actual = _.map(values, function(value) {
|
||||
var wrapped = _(lodashBizarro(value)),
|
||||
unwrapped = wrapped.__wrapped__;
|
||||
unwrapped = wrapped.value();
|
||||
|
||||
return wrapped instanceof _ &&
|
||||
(unwrapped === value || (_.isNaN(unwrapped) && _.isNaN(value)));
|
||||
@@ -4160,10 +4160,10 @@
|
||||
strictEqual(func(array, Boolean), array);
|
||||
});
|
||||
|
||||
test('`_.' + methodName + '` should return the existing wrapped value when chaining', 1, function() {
|
||||
test('`_.' + methodName + '` should not return the existing wrapped value when chaining', 1, function() {
|
||||
if (!isNpm) {
|
||||
var wrapped = _(array);
|
||||
strictEqual(wrapped[methodName](_.noop), wrapped);
|
||||
notStrictEqual(wrapped[methodName](_.noop), wrapped);
|
||||
}
|
||||
else {
|
||||
skipTest();
|
||||
@@ -4352,10 +4352,10 @@
|
||||
deepEqual(_.reduce(array, func, { 'a': 1}), { 'a': 1, 'b': 2, 'c': 3 });
|
||||
});
|
||||
|
||||
test('`_.' + methodName + '` should return the existing wrapped value when chaining', 1, function() {
|
||||
test('`_.' + methodName + '` should not return the existing wrapped value when chaining', 1, function() {
|
||||
if (!isNpm) {
|
||||
var wrapped = _({ 'a': 1 });
|
||||
strictEqual(wrapped[methodName]({ 'b': 2 }), wrapped);
|
||||
notStrictEqual(wrapped[methodName]({ 'b': 2 }), wrapped);
|
||||
}
|
||||
else {
|
||||
skipTest();
|
||||
@@ -7681,9 +7681,19 @@
|
||||
if (!(this instanceof wrapper)) {
|
||||
return new wrapper(value);
|
||||
}
|
||||
if (_.has(value, '__wrapped__')) {
|
||||
var chain = value.__chain__,
|
||||
queue = _.slice(value.__queue__);
|
||||
|
||||
value = value.__wrapped__;
|
||||
}
|
||||
this.__chain__ = chain || false;
|
||||
this.__queue__ = queue || [];
|
||||
this.__wrapped__ = value;
|
||||
}
|
||||
|
||||
wrapper.prototype.value = _.prototype.value;
|
||||
|
||||
var value = ['a'],
|
||||
source = { 'a': function(array) { return array[0]; }, 'b': 'B' };
|
||||
|
||||
@@ -7691,7 +7701,7 @@
|
||||
_.mixin(source);
|
||||
|
||||
strictEqual(_.a(value), 'a');
|
||||
strictEqual(_(value).a().__wrapped__, 'a');
|
||||
strictEqual(_(value).a().value(), 'a');
|
||||
|
||||
delete _.a;
|
||||
delete _.prototype.a;
|
||||
@@ -7736,7 +7746,7 @@
|
||||
var wrapped = wrapper(value),
|
||||
actual = wrapped.a();
|
||||
|
||||
strictEqual(actual.__wrapped__, 'a');
|
||||
strictEqual(actual.value(), 'a');
|
||||
ok(actual instanceof wrapper);
|
||||
|
||||
delete wrapper.a;
|
||||
@@ -7768,7 +7778,7 @@
|
||||
actual = wrapped.a();
|
||||
|
||||
if (options === true || (options && options.chain)) {
|
||||
strictEqual(actual.__wrapped__, 'a', message(func, true));
|
||||
strictEqual(actual.value(), 'a', message(func, true));
|
||||
ok(actual instanceof func, message(func, true));
|
||||
} else {
|
||||
strictEqual(actual, 'a', message(func, false));
|
||||
@@ -7813,7 +7823,7 @@
|
||||
ok(pass);
|
||||
});
|
||||
|
||||
test('should return the existing wrapped value when chaining', 2, function() {
|
||||
test('should not return the existing wrapped value when chaining', 2, function() {
|
||||
if (!isNpm) {
|
||||
_.each([_, wrapper], function(func) {
|
||||
if (func === _) {
|
||||
@@ -7825,7 +7835,7 @@
|
||||
else {
|
||||
wrapped = _(func);
|
||||
actual = wrapped.mixin(source);
|
||||
strictEqual(actual, wrapped);
|
||||
notStrictEqual(actual, wrapped);
|
||||
}
|
||||
delete func.a;
|
||||
delete func.prototype.a;
|
||||
@@ -10175,6 +10185,8 @@
|
||||
});
|
||||
|
||||
ok(actual instanceof _);
|
||||
|
||||
actual.value();
|
||||
strictEqual(intercepted, array);
|
||||
}
|
||||
else {
|
||||
@@ -11888,9 +11900,9 @@
|
||||
];
|
||||
|
||||
_.each(funcs, function(methodName) {
|
||||
test('`_(...).' + methodName + '` should return the existing wrapped value', 1, function() {
|
||||
test('`_(...).' + methodName + '` should not return the existing wrapped value', 1, function() {
|
||||
if (!isNpm) {
|
||||
strictEqual(wrapped[methodName](), wrapped);
|
||||
notStrictEqual(wrapped[methodName](), wrapped);
|
||||
}
|
||||
else {
|
||||
skipTest();
|
||||
|
||||
Reference in New Issue
Block a user