mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-02 16:17:50 +00:00
Make _.extend and alias of _.assign and make _.assign iterate only own enumerable source props to align with ES6.
Former-commit-id: 37ba7c3066c1ea70210346a9bf598e8587e907db
This commit is contained in:
33
build.js
33
build.js
@@ -28,11 +28,11 @@
|
||||
var aliasToRealMap = {
|
||||
'all': 'every',
|
||||
'any': 'some',
|
||||
'assign': 'extend',
|
||||
'collect': 'map',
|
||||
'detect': 'find',
|
||||
'drop': 'rest',
|
||||
'each': 'forEach',
|
||||
'extend': 'assign',
|
||||
'foldl': 'reduce',
|
||||
'foldr': 'reduceRight',
|
||||
'head': 'first',
|
||||
@@ -47,9 +47,9 @@
|
||||
|
||||
/** Used to associate real names with their aliases */
|
||||
var realToAliasMap = {
|
||||
'assign': ['extend'],
|
||||
'contains': ['include'],
|
||||
'every': ['all'],
|
||||
'extend': ['assign'],
|
||||
'filter': ['select'],
|
||||
'find': ['detect'],
|
||||
'first': ['head', 'take'],
|
||||
@@ -66,10 +66,11 @@
|
||||
/** Used to track function dependencies */
|
||||
var dependencyMap = {
|
||||
'after': [],
|
||||
'assign': ['isArguments'],
|
||||
'bind': ['isFunction', 'isObject'],
|
||||
'bindAll': ['bind', 'functions'],
|
||||
'chain': ['mixin'],
|
||||
'clone': ['extend', 'forEach', 'forOwn', 'isArguments', 'isObject', 'isPlainObject'],
|
||||
'clone': ['assign', 'forEach', 'forOwn', 'isArguments', 'isObject', 'isPlainObject'],
|
||||
'compact': [],
|
||||
'compose': [],
|
||||
'contains': ['forEach', 'indexOf', 'isString'],
|
||||
@@ -81,7 +82,6 @@
|
||||
'difference': ['indexOf'],
|
||||
'escape': [],
|
||||
'every': ['forEach', 'isArray'],
|
||||
'extend': ['isArguments'],
|
||||
'filter': ['forEach', 'isArray'],
|
||||
'find': ['forEach'],
|
||||
'first': [],
|
||||
@@ -231,7 +231,6 @@
|
||||
|
||||
/** List of methods used by Underscore */
|
||||
var underscoreMethods = _.without.apply(_, [allMethods].concat([
|
||||
'assign',
|
||||
'forIn',
|
||||
'forOwn',
|
||||
'isPlainObject',
|
||||
@@ -346,7 +345,7 @@
|
||||
' lodash csp Build supporting default Content Security Policy restrictions',
|
||||
' lodash legacy Build tailored for older browsers without ES5 support',
|
||||
' lodash mobile Build with IE < 9 bug fixes & method compilation removed',
|
||||
' lodash strict Build with `_.bindAll`, `_.defaults`, & `_.extend` in strict mode',
|
||||
' lodash strict Build with `_.assign`, `_.bindAll`, & `_.defaults` in strict mode',
|
||||
' lodash underscore Build tailored for projects already using Underscore',
|
||||
' lodash include=... Comma separated method/category names to include in the build',
|
||||
' lodash minus=... Comma separated method/category names to remove from those included in the build',
|
||||
@@ -892,7 +891,7 @@
|
||||
// flag used to specify skipping status updates normally logged to the console
|
||||
var isSilent = isStdOut || options.indexOf('-s') > -1 || options.indexOf('--silent') > -1;
|
||||
|
||||
// flag used to specify `_.bindAll`, `_.extend`, and `_.defaults` are
|
||||
// flag used to specify `_.assign`, `_.bindAll`, and `_.defaults` are
|
||||
// constructed using the "use strict" directive
|
||||
var isStrict = options.indexOf('strict') > -1;
|
||||
|
||||
@@ -933,7 +932,7 @@
|
||||
return match
|
||||
? Function('return {' + match[1].replace(/^{|}$/g, '') + '}')()
|
||||
: result;
|
||||
}, _.extend(_.clone(_.templateSettings), {
|
||||
}, _.assign(_.clone(_.templateSettings), {
|
||||
'moduleId': moduleId
|
||||
}));
|
||||
|
||||
@@ -998,7 +997,7 @@
|
||||
dependencyMap.template = ['defaults', 'escape'];
|
||||
|
||||
if (useUnderscoreClone) {
|
||||
dependencyMap.clone = ['extend', 'isArray'];
|
||||
dependencyMap.clone = ['assign', 'isArray'];
|
||||
}
|
||||
}
|
||||
// add method names required by Backbone and Underscore builds
|
||||
@@ -1068,7 +1067,7 @@
|
||||
source = source.replace(/^( *)function clone[\s\S]+?\n\1}/m, [
|
||||
' function clone(value) {',
|
||||
' return value && objectTypes[typeof value]',
|
||||
' ? (isArray(value) ? slice.call(value) : extend({}, value))',
|
||||
' ? (isArray(value) ? slice.call(value) : assign({}, value))',
|
||||
' : value',
|
||||
' }'
|
||||
].join('\n'));
|
||||
@@ -1108,9 +1107,9 @@
|
||||
' }'
|
||||
].join('\n'));
|
||||
|
||||
// replace `_.extend`
|
||||
source = source.replace(/^( *)var extend *= *createIterator[\s\S]+?\);/m, [
|
||||
' function extend(object) {',
|
||||
// replace `_.assign`
|
||||
source = source.replace(/^( *)var assign *= *createIterator[\s\S]+?\);/m, [
|
||||
' function assign(object) {',
|
||||
' if (!object) {',
|
||||
' return object;',
|
||||
' }',
|
||||
@@ -1309,9 +1308,6 @@
|
||||
}
|
||||
});
|
||||
|
||||
if (!exposeAssign) {
|
||||
source = removeFunction(source, 'assign');
|
||||
}
|
||||
// remove `isArguments` fallback before `isArguments` is transformed by
|
||||
// other parts of the build process
|
||||
if (isRemoved(source, 'isArguments')) {
|
||||
@@ -1379,11 +1375,14 @@
|
||||
});
|
||||
|
||||
if (isUnderscore) {
|
||||
// remove `_.forIn`, `_.forOwn`, and `_.isPlainObject` assignments
|
||||
// remove `_.assign`, `_.forIn`, `_.forOwn`, and `_.isPlainObject` assignments
|
||||
(function() {
|
||||
var snippet = getMethodAssignments(source),
|
||||
modified = snippet;
|
||||
|
||||
if (!exposeAssign) {
|
||||
modified = modified.replace(/(?:\n *\/\/.*\s*)* *lodash\.assign *= *.+\n/, '');
|
||||
}
|
||||
if (!exposeForIn) {
|
||||
modified = modified.replace(/(?:\n *\/\/.*\s*)* *lodash\.forIn *= *.+\n/, '');
|
||||
}
|
||||
|
||||
72
lodash.js
72
lodash.js
@@ -417,6 +417,16 @@
|
||||
'return result'
|
||||
);
|
||||
|
||||
/** Reusable iterator options for `assign` and `defaults` */
|
||||
var assignIteratorOptions = {
|
||||
'args': 'object, source, guard',
|
||||
'top':
|
||||
'for (var argsIndex = 1, argsLength = typeof guard == \'number\' ? 2 : arguments.length; argsIndex < argsLength; argsIndex++) {\n' +
|
||||
' if ((iteratee = arguments[argsIndex])) {',
|
||||
'objectLoop': 'result[index] = value',
|
||||
'bottom': ' }\n}'
|
||||
};
|
||||
|
||||
/**
|
||||
* Reusable iterator options shared by `forEach`, `forIn`, and `forOwn`.
|
||||
*/
|
||||
@@ -427,17 +437,6 @@
|
||||
'objectLoop': 'if (callback(value, index, collection) === false) return result'
|
||||
};
|
||||
|
||||
/** Reusable iterator options for `defaults`, and `extend` */
|
||||
var extendIteratorOptions = {
|
||||
'useHas': false,
|
||||
'args': 'object, source, guard',
|
||||
'top':
|
||||
'for (var argsIndex = 1, argsLength = typeof guard == \'number\' ? 2 : arguments.length; argsIndex < argsLength; argsIndex++) {\n' +
|
||||
' if ((iteratee = arguments[argsIndex])) {',
|
||||
'objectLoop': 'result[index] = value',
|
||||
'bottom': ' }\n}'
|
||||
};
|
||||
|
||||
/** Reusable iterator options for `forIn` and `forOwn` */
|
||||
var forOwnIteratorOptions = {
|
||||
'arrayLoop': null
|
||||
@@ -697,6 +696,25 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Assigns own enumerable properties of source object(s) to the `destination`
|
||||
* object. Subsequent sources will overwrite propery assignments of previous
|
||||
* sources.
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @alias extend
|
||||
* @category Objects
|
||||
* @param {Object} object The destination object.
|
||||
* @param {Object} [source1, source2, ...] The source objects.
|
||||
* @returns {Object} Returns the destination object.
|
||||
* @example
|
||||
*
|
||||
* _.assign({ 'name': 'moe' }, { 'age': 40 });
|
||||
* // => { 'name': 'moe', 'age': 40 }
|
||||
*/
|
||||
var assign = createIterator(assignIteratorOptions);
|
||||
|
||||
/**
|
||||
* Checks if `value` is an `arguments` object.
|
||||
*
|
||||
@@ -756,7 +774,7 @@
|
||||
});
|
||||
|
||||
/**
|
||||
* Iterates over `object`'s own enumerable properties, executing the `callback`
|
||||
* Iterates over an object's own enumerable properties, executing the `callback`
|
||||
* for each property. The `callback` is bound to `thisArg` and invoked with three
|
||||
* arguments; (value, key, object). Callbacks may exit iteration early by explicitly
|
||||
* returning `false`.
|
||||
@@ -915,7 +933,7 @@
|
||||
if (!isObj || !deep) {
|
||||
// don't clone functions
|
||||
return isObj
|
||||
? (isArr ? slice.call(value) : extend({}, value))
|
||||
? (isArr ? slice.call(value) : assign({}, value))
|
||||
: value;
|
||||
}
|
||||
|
||||
@@ -976,29 +994,11 @@
|
||||
* _.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'rainbow' });
|
||||
* // => { 'flavor': 'chocolate', 'sprinkles': 'rainbow' }
|
||||
*/
|
||||
var defaults = createIterator(extendIteratorOptions, {
|
||||
'objectLoop': 'if (result[index] == null) ' + extendIteratorOptions.objectLoop
|
||||
var defaults = createIterator(assignIteratorOptions, {
|
||||
'useHas': false,
|
||||
'objectLoop': 'if (result[index] == null) ' + assignIteratorOptions.objectLoop
|
||||
});
|
||||
|
||||
/**
|
||||
* Assigns enumerable properties of the source object(s) to the `destination`
|
||||
* object. Subsequent sources will overwrite propery assignments of previous
|
||||
* sources.
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @alias assign
|
||||
* @category Objects
|
||||
* @param {Object} object The destination object.
|
||||
* @param {Object} [source1, source2, ...] The source objects.
|
||||
* @returns {Object} Returns the destination object.
|
||||
* @example
|
||||
*
|
||||
* _.extend({ 'name': 'moe' }, { 'age': 40 });
|
||||
* // => { 'name': 'moe', 'age': 40 }
|
||||
*/
|
||||
var extend = createIterator(extendIteratorOptions);
|
||||
|
||||
/**
|
||||
* Creates a sorted array of all enumerable properties, own and inherited,
|
||||
* of `object` that have function values.
|
||||
@@ -4079,6 +4079,7 @@
|
||||
lodash.VERSION = '0.9.2';
|
||||
|
||||
// assign static methods
|
||||
lodash.assign = assign;
|
||||
lodash.after = after;
|
||||
lodash.bind = bind;
|
||||
lodash.bindAll = bindAll;
|
||||
@@ -4095,7 +4096,6 @@
|
||||
lodash.difference = difference;
|
||||
lodash.escape = escape;
|
||||
lodash.every = every;
|
||||
lodash.extend = extend;
|
||||
lodash.filter = filter;
|
||||
lodash.find = find;
|
||||
lodash.first = first;
|
||||
@@ -4177,11 +4177,11 @@
|
||||
// assign aliases
|
||||
lodash.all = every;
|
||||
lodash.any = some;
|
||||
lodash.assign = extend;
|
||||
lodash.collect = map;
|
||||
lodash.detect = find;
|
||||
lodash.drop = rest;
|
||||
lodash.each = forEach;
|
||||
lodash.extend = assign;
|
||||
lodash.foldl = reduce;
|
||||
lodash.foldr = reduceRight;
|
||||
lodash.head = first;
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
var aliasToRealMap = {
|
||||
'all': 'every',
|
||||
'any': 'some',
|
||||
'assign': 'extend',
|
||||
'collect': 'map',
|
||||
'detect': 'find',
|
||||
'drop': 'rest',
|
||||
'each': 'forEach',
|
||||
'extend': 'assign',
|
||||
'foldl': 'reduce',
|
||||
'foldr': 'reduceRight',
|
||||
'head': 'first',
|
||||
@@ -37,9 +37,9 @@
|
||||
|
||||
/** Used to associate real names with their aliases */
|
||||
var realToAliasMap = {
|
||||
'assign': ['extend'],
|
||||
'contains': ['include'],
|
||||
'every': ['all'],
|
||||
'extend': ['assign'],
|
||||
'filter': ['select'],
|
||||
'find': ['detect'],
|
||||
'first': ['head', 'take'],
|
||||
@@ -242,7 +242,6 @@
|
||||
|
||||
/** List of methods used by Underscore */
|
||||
var underscoreMethods = _.without.apply(_, [allMethods].concat([
|
||||
'assign',
|
||||
'forIn',
|
||||
'forOwn',
|
||||
'isPlainObject',
|
||||
|
||||
74
test/test.js
74
test/test.js
@@ -163,6 +163,42 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.assign');
|
||||
|
||||
(function() {
|
||||
test('should not error on `null` or `undefined` sources (test in IE < 9)', function() {
|
||||
try {
|
||||
deepEqual(_.assign({}, null, undefined, { 'a': 1 }), { 'a': 1 });
|
||||
} catch(e) {
|
||||
ok(false);
|
||||
}
|
||||
});
|
||||
|
||||
test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() {
|
||||
function Foo() {}
|
||||
Foo.prototype.c = 3;
|
||||
|
||||
Foo.a = 1;
|
||||
Foo.b = 2;
|
||||
|
||||
var expected = { 'a': 1, 'b': 2 };
|
||||
deepEqual(_.assign({}, Foo), expected);
|
||||
|
||||
Foo.prototype = { 'c': 3 };
|
||||
deepEqual(_.assign({}, Foo), expected);
|
||||
});
|
||||
|
||||
test('should work with `_.reduce`', function() {
|
||||
var actual = { 'a': 1},
|
||||
array = [{ 'b': 2 }, { 'c': 3 }];
|
||||
|
||||
_.reduce(array, _.assign, actual);
|
||||
deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.bind');
|
||||
|
||||
(function() {
|
||||
@@ -385,45 +421,9 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.extend');
|
||||
|
||||
(function() {
|
||||
test('should not error on `null` or `undefined` sources (test in IE < 9)', function() {
|
||||
try {
|
||||
deepEqual(_.extend({}, null, undefined, { 'a': 1 }), { 'a': 1 });
|
||||
} catch(e) {
|
||||
ok(false);
|
||||
}
|
||||
});
|
||||
|
||||
test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() {
|
||||
function Foo() {}
|
||||
Foo.prototype.c = 3;
|
||||
|
||||
Foo.a = 1;
|
||||
Foo.b = 2;
|
||||
|
||||
var expected = { 'a': 1, 'b': 2 };
|
||||
deepEqual(_.extend({}, Foo), expected);
|
||||
|
||||
Foo.prototype = { 'c': 3 };
|
||||
deepEqual(_.extend({}, Foo), expected);
|
||||
});
|
||||
|
||||
test('should work with `_.reduce`', function() {
|
||||
var actual = { 'a': 1},
|
||||
array = [{ 'b': 2 }, { 'c': 3 }];
|
||||
|
||||
_.reduce(array, _.extend, actual);
|
||||
deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('strict mode checks');
|
||||
|
||||
_.each(['bindAll', 'defaults', 'extend'], function(methodName) {
|
||||
_.each(['assign', 'bindAll', 'defaults'], function(methodName) {
|
||||
var func = _[methodName];
|
||||
|
||||
test('lodash.' + methodName + ' should not throw strict mode errors', function() {
|
||||
|
||||
Reference in New Issue
Block a user