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)