Skip to content

Instantly share code, notes, and snippets.

@silvenon
Last active August 29, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save silvenon/befcb21a6e54edaa9189 to your computer and use it in GitHub Desktop.
Save silvenon/befcb21a6e54edaa9189 to your computer and use it in GitHub Desktop.
Why is using Browserify a good idea again? There's absolutely nothing I can do to reduce the size of bundled JS if it contains things I don't need.

These are two forEach functions; the one I wrote vs. the one I imported from lodash via Browserify.

(I removed the comments to be more fair.)

window._ = {};
window._.forEach = function (ar, fn) {
for (var i = 0; i < ar.length; i++) {
fn.call(this, ar[i]);
}
};
// var forEach = require('lodash/collection/forEach');
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var forEach = require('lodash/collection/forEach');
},{"lodash/collection/forEach":2}],2:[function(require,module,exports){
var arrayEach = require('../internal/arrayEach'),
baseEach = require('../internal/baseEach'),
createForEach = require('../internal/createForEach');
var forEach = createForEach(arrayEach, baseEach);
module.exports = forEach;
},{"../internal/arrayEach":3,"../internal/baseEach":4,"../internal/createForEach":12}],3:[function(require,module,exports){
function arrayEach(array, iteratee) {
var index = -1,
length = array.length;
while (++index < length) {
if (iteratee(array[index], index, array) === false) {
break;
}
}
return array;
}
module.exports = arrayEach;
},{}],4:[function(require,module,exports){
var baseForOwn = require('./baseForOwn'),
createBaseEach = require('./createBaseEach');
var baseEach = createBaseEach(baseForOwn);
module.exports = baseEach;
},{"./baseForOwn":6,"./createBaseEach":10}],5:[function(require,module,exports){
var createBaseFor = require('./createBaseFor');
var baseFor = createBaseFor();
module.exports = baseFor;
},{"./createBaseFor":11}],6:[function(require,module,exports){
var baseFor = require('./baseFor'),
keys = require('../object/keys');
function baseForOwn(object, iteratee) {
return baseFor(object, iteratee, keys);
}
module.exports = baseForOwn;
},{"../object/keys":23,"./baseFor":5}],7:[function(require,module,exports){
function baseProperty(key) {
return function(object) {
return object == null ? undefined : object[key];
};
}
module.exports = baseProperty;
},{}],8:[function(require,module,exports){
function baseToString(value) {
if (typeof value == 'string') {
return value;
}
return value == null ? '' : (value + '');
}
module.exports = baseToString;
},{}],9:[function(require,module,exports){
var identity = require('../utility/identity');
function bindCallback(func, thisArg, argCount) {
if (typeof func != 'function') {
return identity;
}
if (thisArg === undefined) {
return func;
}
switch (argCount) {
case 1: return function(value) {
return func.call(thisArg, value);
};
case 3: return function(value, index, collection) {
return func.call(thisArg, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(thisArg, accumulator, value, index, collection);
};
case 5: return function(value, other, key, object, source) {
return func.call(thisArg, value, other, key, object, source);
};
}
return function() {
return func.apply(thisArg, arguments);
};
}
module.exports = bindCallback;
},{"../utility/identity":27}],10:[function(require,module,exports){
var getLength = require('./getLength'),
isLength = require('./isLength'),
toObject = require('./toObject');
function createBaseEach(eachFunc, fromRight) {
return function(collection, iteratee) {
var length = collection ? getLength(collection) : 0;
if (!isLength(length)) {
return eachFunc(collection, iteratee);
}
var index = fromRight ? length : -1,
iterable = toObject(collection);
while ((fromRight ? index-- : ++index < length)) {
if (iteratee(iterable[index], index, iterable) === false) {
break;
}
}
return collection;
};
}
module.exports = createBaseEach;
},{"./getLength":13,"./isLength":15,"./toObject":18}],11:[function(require,module,exports){
var toObject = require('./toObject');
function createBaseFor(fromRight) {
return function(object, iteratee, keysFunc) {
var iterable = toObject(object),
props = keysFunc(object),
length = props.length,
index = fromRight ? length : -1;
while ((fromRight ? index-- : ++index < length)) {
var key = props[index];
if (iteratee(iterable[key], key, iterable) === false) {
break;
}
}
return object;
};
}
module.exports = createBaseFor;
},{"./toObject":18}],12:[function(require,module,exports){
var bindCallback = require('./bindCallback'),
isArray = require('../lang/isArray');
function createForEach(arrayFunc, eachFunc) {
return function(collection, iteratee, thisArg) {
return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
? arrayFunc(collection, iteratee)
: eachFunc(collection, bindCallback(iteratee, thisArg, 3));
};
}
module.exports = createForEach;
},{"../lang/isArray":20,"./bindCallback":9}],13:[function(require,module,exports){
var baseProperty = require('./baseProperty');
var getLength = baseProperty('length');
module.exports = getLength;
},{"./baseProperty":7}],14:[function(require,module,exports){
var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
function isIndex(value, length) {
value = +value;
length = length == null ? MAX_SAFE_INTEGER : length;
return value > -1 && value % 1 == 0 && value < length;
}
module.exports = isIndex;
},{}],15:[function(require,module,exports){
var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
function isLength(value) {
return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}
module.exports = isLength;
},{}],16:[function(require,module,exports){
function isObjectLike(value) {
return !!value && typeof value == 'object';
}
module.exports = isObjectLike;
},{}],17:[function(require,module,exports){
var isArguments = require('../lang/isArguments'),
isArray = require('../lang/isArray'),
isIndex = require('./isIndex'),
isLength = require('./isLength'),
keysIn = require('../object/keysIn'),
support = require('../support');
var objectProto = Object.prototype;
var hasOwnProperty = objectProto.hasOwnProperty;
function shimKeys(object) {
var props = keysIn(object),
propsLength = props.length,
length = propsLength && object.length;
var allowIndexes = length && isLength(length) &&
(isArray(object) || (support.nonEnumArgs && isArguments(object)));
var index = -1,
result = [];
while (++index < propsLength) {
var key = props[index];
if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
result.push(key);
}
}
return result;
}
module.exports = shimKeys;
},{"../lang/isArguments":19,"../lang/isArray":20,"../object/keysIn":24,"../support":26,"./isIndex":14,"./isLength":15}],18:[function(require,module,exports){
var isObject = require('../lang/isObject');
function toObject(value) {
return isObject(value) ? value : Object(value);
}
module.exports = toObject;
},{"../lang/isObject":22}],19:[function(require,module,exports){
var isLength = require('../internal/isLength'),
isObjectLike = require('../internal/isObjectLike');
var argsTag = '[object Arguments]';
var objectProto = Object.prototype;
var objToString = objectProto.toString;
function isArguments(value) {
var length = isObjectLike(value) ? value.length : undefined;
return isLength(length) && objToString.call(value) == argsTag;
}
module.exports = isArguments;
},{"../internal/isLength":15,"../internal/isObjectLike":16}],20:[function(require,module,exports){
var isLength = require('../internal/isLength'),
isNative = require('./isNative'),
isObjectLike = require('../internal/isObjectLike');
var arrayTag = '[object Array]';
var objectProto = Object.prototype;
var objToString = objectProto.toString;
var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray;
var isArray = nativeIsArray || function(value) {
return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
};
module.exports = isArray;
},{"../internal/isLength":15,"../internal/isObjectLike":16,"./isNative":21}],21:[function(require,module,exports){
var escapeRegExp = require('../string/escapeRegExp'),
isObjectLike = require('../internal/isObjectLike');
var funcTag = '[object Function]';
var reIsHostCtor = /^\[object .+?Constructor\]$/;
var objectProto = Object.prototype;
var fnToString = Function.prototype.toString;
var objToString = objectProto.toString;
var reIsNative = RegExp('^' +
escapeRegExp(objToString)
.replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);
function isNative(value) {
if (value == null) {
return false;
}
if (objToString.call(value) == funcTag) {
return reIsNative.test(fnToString.call(value));
}
return isObjectLike(value) && reIsHostCtor.test(value);
}
module.exports = isNative;
},{"../internal/isObjectLike":16,"../string/escapeRegExp":25}],22:[function(require,module,exports){
function isObject(value) {
var type = typeof value;
return type == 'function' || (!!value && type == 'object');
}
module.exports = isObject;
},{}],23:[function(require,module,exports){
var isLength = require('../internal/isLength'),
isNative = require('../lang/isNative'),
isObject = require('../lang/isObject'),
shimKeys = require('../internal/shimKeys');
var nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys;
var keys = !nativeKeys ? shimKeys : function(object) {
if (object) {
var Ctor = object.constructor,
length = object.length;
}
if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
(typeof object != 'function' && isLength(length))) {
return shimKeys(object);
}
return isObject(object) ? nativeKeys(object) : [];
};
module.exports = keys;
},{"../internal/isLength":15,"../internal/shimKeys":17,"../lang/isNative":21,"../lang/isObject":22}],24:[function(require,module,exports){
var isArguments = require('../lang/isArguments'),
isArray = require('../lang/isArray'),
isIndex = require('../internal/isIndex'),
isLength = require('../internal/isLength'),
isObject = require('../lang/isObject'),
support = require('../support');
var objectProto = Object.prototype;
var hasOwnProperty = objectProto.hasOwnProperty;
function keysIn(object) {
if (object == null) {
return [];
}
if (!isObject(object)) {
object = Object(object);
}
var length = object.length;
length = (length && isLength(length) &&
(isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) || 0;
var Ctor = object.constructor,
index = -1,
isProto = typeof Ctor == 'function' && Ctor.prototype === object,
result = Array(length),
skipIndexes = length > 0;
while (++index < length) {
result[index] = (index + '');
}
for (var key in object) {
if (!(skipIndexes && isIndex(key, length)) &&
!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
result.push(key);
}
}
return result;
}
module.exports = keysIn;
},{"../internal/isIndex":14,"../internal/isLength":15,"../lang/isArguments":19,"../lang/isArray":20,"../lang/isObject":22,"../support":26}],25:[function(require,module,exports){
var baseToString = require('../internal/baseToString');
var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
reHasRegExpChars = RegExp(reRegExpChars.source);
function escapeRegExp(string) {
string = baseToString(string);
return (string && reHasRegExpChars.test(string))
? string.replace(reRegExpChars, '\\$&')
: string;
}
module.exports = escapeRegExp;
},{"../internal/baseToString":8}],26:[function(require,module,exports){
(function (global){
var objectProto = Object.prototype;
var document = (document = global.window) && document.document;
var propertyIsEnumerable = objectProto.propertyIsEnumerable;
var support = {};
(function(x) {
var Ctor = function() { this.x = x; },
object = { '0': x, 'length': x },
props = [];
Ctor.prototype = { 'valueOf': x, 'y': x };
for (var key in new Ctor) { props.push(key); }
support.funcDecomp = /\bthis\b/.test(function() { return this; });
support.funcNames = typeof Function.name == 'string';
try {
support.dom = document.createDocumentFragment().nodeType === 11;
} catch(e) {
support.dom = false;
}
try {
support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1);
} catch(e) {
support.nonEnumArgs = true;
}
}(1, 0));
module.exports = support;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],27:[function(require,module,exports){
function identity(value) {
return value;
}
module.exports = identity;
},{}]},{},[1])
@jdalton
Copy link

jdalton commented Apr 19, 2015

Try require('lodash/internal/arrayEach') and browserify --plugin bundle-collapser/plugin
which Uglifies to 351 bytes gzipped, 314 bytes of which is the Browserify boilerplate.

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/**
 * A specialized version of `_.forEach` for arrays without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Array} array The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns `array`.
 */
function arrayEach(array, iteratee) {
  var index = -1,
      length = array.length;

  while (++index < length) {
    if (iteratee(array[index], index, array) === false) {
      break;
    }
  }
  return array;
}

module.exports = arrayEach;

},{}],2:[function(require,module,exports){
module.exports = require(1);

},{"1":1}]},{},[2]);

@silvenon
Copy link
Author

Wow, that is much better 😅

But it just goes to show how you don't really have good idea what's being included while coding. This is an internal function that I would waste more time finding than writing my own.

@jdalton
Copy link

jdalton commented Apr 19, 2015

Wow, that is much better 😅

Modules rock! 😸

But it just goes to show how you don't really have good idea what's being included while coding

It looks like you have a good idea of the scope of functionality you want and _.each is simply more functionality than you need (with support for object iteration, fixes for Safari JIT bugs, etc.). The lodash internal at least aligns more closely with _.each than the written alternative, providing the same iteratee arguments & allowing iteration to exit early.

@ljharb
Copy link

ljharb commented Apr 19, 2015

"less" isn't "better". "correct" is better.

Your forEach doesn't handle objects, which lodash's does, it also is useless since Array.prototype.forEach already exists natively - so if you're just working with arrays, why would you want a utility function at all? Yours is also broken with its handling of "this", and unlike forEach, doesn't pass the index, or the entire array, to the callback.

See https://twitter.com/paul_irish/status/227203681462927361 and https://twitter.com/trek/status/227082154109186049

@mattdesl
Copy link

If you just want a simple forEach implementation:

npm install foreach --save

Then;

var each = require('foreach')
each(array, fn, ctx)

https://www.npmjs.com/package/foreach

@jdalton Is internal/ really safe to require? Do breaking changes in internal/ lead to major version bumps?

@jdalton
Copy link

jdalton commented Apr 19, 2015

@mattdesl

If you just want a simple forEach implementation:

npm install foreach --save

Careful, foreach hits an iOS JIT bug that affects Safari on at least iOS 8.1-8.3 ARM64.

Is internal/ really safe to require? Do breaking changes in internal/ lead to major version bumps?

Internals are more relaxed than external but we try for internals to be safe with the ~ range.

@millermedeiros
Copy link

Another option is MOUT require('mout/array/forEach')

@millermedeiros
Copy link

Problem of roll your own solutions is that it will probably contain bugs, less tests and no documentation... There is always a cost on loading external dependencies but in many cases it does pay off. I would definitely not start MOUT if the modular lodash existed back in 2011.

@ljharb
Copy link

ljharb commented Apr 19, 2015

A simpler one: var forEach = Function.bind.call(Function.call, Array.prototype.forEach)

@silvenon
Copy link
Author

A simpler one: var forEach = Function.bind.call(Function.call, Array.prototype.forEach)

Nice one 👍 Yeah, I know mine sucks, it wasn't a very good example, but I'm just incredibly frustrated with trying to make it work and "fixing" other people's libs when the benefit is not clear to me anymore. Also, publishing Node packages which can't be used in Node is a very weird idea to me, am I the only one? I'm going to paraphrase a feature request:

Hey, could you please convert your client-side JavaScript library to Node, so I can convert it back to client-side?

I'm probably wrong and just in a moment of frustration, I'll get it eventually.

See https://twitter.com/paul_irish/status/227203681462927361 and https://twitter.com/trek/status/227082154109186049

So why do we bother with packages at all? Including vendor files is a lot easier, we don't care about a little redundant code then?

@silvenon
Copy link
Author

Problem of roll your own solutions is that it will probably contain bugs, less tests and no documentation...

You're right, it does have that drawback.

@ljharb
Copy link

ljharb commented Apr 21, 2015

@silvenon "why do we bother with packages at all" - packages are the same as vendor files, but better encapsulated. "easier" isn't important, "reliable" is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment