@samitouri / QOS-React-2 / commits / 50c81d5fe6

Make createClass 10-15% faster on complex specs

Ben Alpert committed Nov 25, 2015 at 18:23 UTC 50c81d5fe68096fec9e4c5ff6c6cee73cd07704e
1 file changed +16 -17
src/isomorphic/classic/class/ReactClass.js
+16 -17
@@ -414,7 +414,7 @@ function validateTypeDef(Constructor, typeDef, location) {
414 }
415 }
416
417 -function validateMethodOverride(proto, name) {
417 +function validateMethodOverride(isAlreadyDefined, name) {
418 var specPolicy = ReactClassInterface.hasOwnProperty(name) ?
419 ReactClassInterface[name] :
420 null;
@@ -431,7 +431,7 @@ function validateMethodOverride(proto, name) {
431 }
432
433 // Disallow defining methods more than once unless explicitly allowed.
434 - if (proto.hasOwnProperty(name)) {
434 + if (isAlreadyDefined) {
435 invariant(
436 specPolicy === SpecPolicy.DEFINE_MANY ||
437 specPolicy === SpecPolicy.DEFINE_MANY_MERGED,
@@ -465,6 +465,7 @@ function mixSpecIntoComponent(Constructor, spec) {
465 );
466
467 var proto = Constructor.prototype;
468 + var autoBindPairs = proto.__reactAutoBindPairs;
469
470 // By handling mixins before any other properties, we ensure the same
471 // chaining order is applied to methods with DEFINE_MANY policy, whether
@@ -484,7 +485,8 @@ function mixSpecIntoComponent(Constructor, spec) {
485 }
486
487 var property = spec[name];
487 - validateMethodOverride(proto, name);
488 + var isAlreadyDefined = proto.hasOwnProperty(name);
489 + validateMethodOverride(isAlreadyDefined, name);
490
491 if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
492 RESERVED_SPEC_KEYS[name](Constructor, property);
@@ -495,7 +497,6 @@ function mixSpecIntoComponent(Constructor, spec) {
497 // 2. Overridden methods (that were mixed in).
498 var isReactClassMethod =
499 ReactClassInterface.hasOwnProperty(name);
498 - var isAlreadyDefined = proto.hasOwnProperty(name);
500 var isFunction = typeof property === 'function';
501 var shouldAutoBind =
502 isFunction &&
@@ -504,10 +505,7 @@ function mixSpecIntoComponent(Constructor, spec) {
505 spec.autobind !== false;
506
507 if (shouldAutoBind) {
507 - if (!proto.__reactAutoBindMap) {
508 - proto.__reactAutoBindMap = {};
509 - }
510 - proto.__reactAutoBindMap[name] = property;
508 + autoBindPairs.push(name, property);
509 proto[name] = property;
510 } else {
511 if (isAlreadyDefined) {
@@ -700,14 +698,14 @@ function bindAutoBindMethod(component, method) {
698 * @param {object} component Component whose method is going to be bound.
699 */
700 function bindAutoBindMethods(component) {
703 - for (var autoBindKey in component.__reactAutoBindMap) {
704 - if (component.__reactAutoBindMap.hasOwnProperty(autoBindKey)) {
705 - var method = component.__reactAutoBindMap[autoBindKey];
706 - component[autoBindKey] = bindAutoBindMethod(
707 - component,
708 - method
709 - );
710 - }
701 + var pairs = component.__reactAutoBindPairs;
702 + for (var i = 0; i < pairs.length; i += 2) {
703 + var autoBindKey = pairs[i];
704 + var method = pairs[i + 1];
705 + component[autoBindKey] = bindAutoBindMethod(
706 + component,
707 + method
708 + );
709 }
710 }
711
@@ -812,7 +810,7 @@ var ReactClass = {
810 }
811
812 // Wire up auto-binding
815 - if (this.__reactAutoBindMap) {
813 + if (this.__reactAutoBindPairs.length) {
814 bindAutoBindMethods(this);
815 }
816
@@ -846,6 +844,7 @@ var ReactClass = {
844 };
845 Constructor.prototype = new ReactClassComponent();
846 Constructor.prototype.constructor = Constructor;
847 + Constructor.prototype.__reactAutoBindPairs = [];
848
849 injectedMixins.forEach(
850 mixSpecIntoComponent.bind(null, Constructor)