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