My object is not updated by reference, what is wrong with the logic?

I have been working with this error for several days, and I think I have identified a problem area, but I'm not sure why it does not work. I think this may be due to the problem of passing the object by reference , but if in this case I'm not sure how to apply this solution to my situation.

Basically, I work (as a learning experience) with my own implementation of dependency injection (although I was told that my structure is actually called AMD , I will continue to use "DI" until I understand more about the difference). Therefore, I will briefly explain my code, and then highlight the problematic part.


Syntax:

This is what my code should do, it's just a very simple DI.

I created a region with a string path, using "/scopeName/subScopeName:componentName"to select a region, so that code users can select a region when defining a component in a simple way, using ":"to select a component from a region.

There are no interfaces, since it is so easy to type check in JS. There are no special types of components, such as factories, values, etc. Each component is handled the same way.

var JHTML = new Viziion('JHTML');
JHTML.addScope('/generate');

/* ... snip ... */

JHTML.addComponent('/generate:process', function(nodes) {
  /* ... snip - the code inside isn't important here - snip ..*/
}).inject(['/generate:jsonInput']);

The function injectsimply takes an array of component paths in the order in which the component parameters are expected.

Hooks are the components stored in the property hooks, and then there is a function returnUserHandlethat will return an object consisting only of hooks, so all functions are hidden in the closures, and you can feed the user code just used methods.

JHTML.addHook('generate', function(jsonInput, process) {
   var html = process(jsonInput);
   return html;
}).inject(['/generate:jsonInput', '/generate:process']);

var handle = JHTML.returnUserHandle();

/* HTML Generator Syntax - Client */

console.log(handle.generate());

Problem:

inject , focus, , that.focus ( this.focus) , addComponent inject, - focus addComponent focusComponent, inject "" , :

that.focus = function() {
   that.focus.apply(null, dependencies);
};

, () , , . . , , that.focus . that.focus , .

?


:

. , , , , , .

    /* Dependency Injection Framework - viziion.js */

    function Viziion() {
      var that = this;

      //here the focus property I mentioned
      this.focus = null;

      this.scope = {
        '/': {
          'subScopes': {},
          'components': {}
        }
      };
      this.hooks = {};

      this.addScope = function(scopeName) {
        /* the way this works inst relevant to the problem */
      };

      this.addComponent = function(componentName, func) {

        var scopeArray = // snip 
          // snip - just code to read the component path

          for (var i = 0; i <= scopeArray.length; i++) {
            if (scopeArray[i] !== "") {
              if (scope.subScopes[scopeArray[i]]) {
                scope = scope.subScopes[scopeArray[i]];
              } else if (i == scopeArray.length) {

                // And here where I add the component to the scope model
                // and reference that component in the focus property
                scope.components[scopeName] = func;
                that.focus = scope.components[scopeName];

              } else {
                throw 'Scope path is invalid.';
              }
            }
          }
      } else {
        throw 'Path does not include a component.';
      }
      return that;
    };

    this.returnComponent = function(componentName, callback) {
      /* ... snip ... */
    };

    this.addHook = function(hookName, func) {
      /* ... snip ... */
    };

    this.inject = function(dependencyArray) {
      if (dependencyArray) {
        var dependencies = [];
        for (var i = 0; i < dependencyArray.length; i++) {
          that.returnComponent(dependencyArray[i], function(dependency) {
            dependencies.push(dependency);
          });
        }
        that.focus = function() {
          that.focus.apply(null, dependencies);
        };
        return that;
      }
    };

    /* ... snip - focusComponent - snip ... */

    /* ... snip - returnUserHandle - snip ... */
Hide result

, , "", HTML.

TypeError: undefined is not a function, var html = process(jsonInput);.


, , :

/* Dependency Injection Framework - viziion.js */

function Viziion(appName) {
  if (typeof appName == 'string') {
    var that = this;
    this.name = appName;
    this.focus = null;
    this.scope = {
      '/': {
        'subScopes': {},
        'components': {}
      }
    };
    this.hooks = {};

    this.addScope = function(scopeName) {
      if (typeof scopeName == 'string') {
        var scopeArray = scopeName.split('/');
        var scope = that.scope['/'];
        for (var i = 0; i < scopeArray.length; i++) {
          if (scopeArray[i] !== "") {
            if (scope.subScopes[scopeArray[i]]) {
              scope = scope.subScopes[scopeArray[i]];
            } else {
              scope.subScopes[scopeArray[i]] = {
                'subScopes': {},
                'components': {}
              };
            }
          }
        }
      } else {
        throw 'Scope path must be a string.';
      }
      return that;
    };

    this.addComponent = function(componentName, func) {
      if (typeof componentName == 'string') {
        var scopeArray = componentName.split(':');
        if (scopeArray.length == 2) {
          var scope = that.scope['/'];
          var scopeName = scopeArray[1];
          scopeArray = scopeArray[0].split('/');
          for (var i = 0; i <= scopeArray.length; i++) {
            if (scopeArray[i] !== "") {
              if (scope.subScopes[scopeArray[i]]) {
                scope = scope.subScopes[scopeArray[i]];
              } else if (i == scopeArray.length) {
                scope.components[scopeName] = func;
                that.focus = scope.components[scopeName];
              } else {
                throw 'Scope path is invalid.';
              }
            }
          }
        } else {
          throw 'Path does not include a component.';
        }
      } else {
        throw 'Component path must be a string.';
      }
      return that;
    };

    this.returnComponent = function(componentName, callback) {
      if (typeof componentName == 'string') {
        var scopeArray = componentName.split(':');
        if (scopeArray.length == 2) {
          var scope = that.scope['/'];
          var scopeName = scopeArray[1];
          scopeArray = scopeArray[0].split('/');
          for (var i = 0; i <= scopeArray.length; i++) {
            if (scopeArray[i] !== "") {
              if (i == scopeArray.length) {
                callback(scope.components[scopeName]);
              } else if (scope.subScopes[scopeArray[i]]) {
                scope = scope.subScopes[scopeArray[i]];
              } else {
                throw 'Scope path is invalid.';
              }
            }
          }
        } else {
          throw 'Path does not include a component.';
        }
      } else {
        throw 'Component path must be a string.';
      }
    };

    this.addHook = function(hookName, func) {
      if (typeof hookName == 'string') {
        that.hooks[hookName] = func;
        that.focus = that.hooks[hookName];
      } else {
        throw 'Hook name must be a string.';
      }
      return that;
    };

    this.inject = function(dependencyArray) {
      if (dependencyArray) {
        var dependencies = [];
        for (var i = 0; i < dependencyArray.length; i++) {
          that.returnComponent(dependencyArray[i], function(dependency) {
            dependencies.push(dependency);
          });
        }
        console.log(that.focus);
        that.focus = function() {
          that.focus.apply(null, dependencies);
        };
        console.log(that.focus);
        console.log(that.scope);
        return that;
      }
    };

    this.focusComponent = function(componentPath) {
      that.focus = that.returnUserHandle(componentPath);
    };

    this.returnUserHandle = function() {
      return that.hooks;
    };

  } else {
    throw 'Viziion name must be a string.';
  }
}

/* JSON HTML Generator - A Simple Library Using Viziion */

var JHTML = new Viziion('JHTML');

JHTML.addScope('/generate');

JHTML.addComponent('/generate:jsonInput', [{
  tag: '!DOCTYPEHTML'
}, {
  tag: 'html',
  children: [{
    tag: 'head',
    children: []
  }, {
    tag: 'body',
    children: []
  }]
}]);

JHTML.addComponent('/generate:process', function(nodes) {
  var html = [];
  var loop = function() {
    for (var i = 0; i < nodes.length; i++) {
      if (nodes[i].tag) {
        html.push('<' + tag + '>');
        if (nodes[i].children) {
          loop();
        }
        html.push('</' + tag + '>');
        return html;
      } else {
        throw '[JHTML] Bad syntax: Tag type is not defined on node.';
      }
    }
  };
}).inject(['/generate:jsonInput']);



JHTML.addHook('generate', function(jsonInput, process) {
  console.log('Process func arg:');
  console.log(process);
  var html = process(jsonInput);
  return html;
}).inject(['/generate:jsonInput', '/generate:process']);

var handle = JHTML.returnUserHandle();

/* HTML Generator Syntax - Client */

console.log(handle.generate());
Hide result
+4
1

, . .

,

, , , , , this.

, this .

:

function A () {
  var that = this;
  this.prop = 1;
  this.method = function () {
    console.log(that.prop);
  };
}

new A().method();

:

function A () {
  this.prop = 1;

  this.method = function () {
    console.log(this.prop);
  };
}

new A().method();

method .bind, .call .apply.

? , this, . .

, method.

function A () {
  this.prop = 1;
}

A.prototype.method = function () {
  console.log(this.prop);
};

new A().method();
new A().method();

, , (!).

, ( "" ), , , .

.

.

. , , , , . , , .

.

, . throw - , throw , - 27 .

// Not great
if (typeof input === 'string') {
  ...
} else throw 'it away';


// Better
if (typeof input !== 'string') throw 'it away';
...

- continue. .

, . OP.

// Not great
for (var i = 0; i < myArray.length; i++) {
  if (myArray[i] > 5) callback(myArray[i]);

  internalArray.push(myArray[i]);
}

// Better
var len = myArray.length, element;

for (var i = 0; i < len; i++) {
  element = myArray[i];

  if (element > 5) callback(element);

  internalArray.push(element);
}

, .

()

-, ? . , .

, - โ€‹โ€‹ .

that.focus = function() {
  that.focus.apply(null, dependencies);
};

inject. . , . , , focus that . .

, , process .

- focus. . , . , "" .

focus (, , ) , , - inject. / inject .

process . , . handle.generate() undefined.

()

, ? , - , . , . , inject, .

, ?

, ? , , .

focus .

focus, , field ( /) fragment ( , , ).

inject, depedancies, bind focus field.

: , this / .

:

var focus = this.focus,
    fragment = this.fragment,
    field = this.field,
    hook = function hook () {
      return this.apply(null, arguments);
    }, func;

dependencies.unshift(focus);
func = Function.prototype.bind.apply(hook, dependencies);

if (fragment) fragment[field] = func;
else this.hooks[field] = func;

, , . , , "" . ( , hook.bind.apply, . , .)

dependencies.unshift(focus);
func = Function.prototype.bind.apply(hook, dependencies);

focus ( ) . .

Function.prototype.bind Function.prototype.apply (, . ).

hook apply.

hook , this , apply. , bind, .

, .

: focusComponent. . , focusComponent , focus, field fragment.

- process. . , .

JHTML.addComponent('/generate:process', function (nodes) {
  return (function build (struct, nodes) {
    var length = nodes.length, node, tag;

    for (var i = 0; i < length; i++) {
      node = nodes[i];
      tag = node.tag;

      if (!tag) throw '[JHTML] Bad syntax: Tag type is not defined on node.';

      struct.push('<' + tag + '>');

      if (node.children) {
        build(struct, node.children)
        struct.push('</' + tag + '>');
      }
    }

    return struct;
  }([], nodes));
}).inject(['/generate:jsonInput']);
Hide result

. , , .

/* Dependency Injection Framework - viziion.js */

function Scope () {
  this.subScopes = {};
  this.components = {};
}

function Viziion (appName) {
  if (typeof appName !== 'string') throw 'Viziion name must be a string.';

  this.name = appName;
  this.working = this.field = this.focus = null
  this.scope = { '/': new Scope() };
  this.hooks = {};
}

Viziion.prototype.addScope = function (scopeName) {
  if (typeof scopeName !== 'string') throw 'Scope path must be a string.';

  var scopeArray = scopeName.split('/'),
      scope = this.scope['/'],
      len = scopeArray.length,
      element, sub;

  for (var i = 0; i < len; i++) {
    element = scopeArray[i];
    if (element === '') continue;

    sub = scope.subScopes[element]

    if (sub) scope = sub;
    else scope.subScopes[element] = new Scope();
  }

  return this;
};

Viziion.prototype.addComponent = function (componentName, func) {
  if (typeof componentName !== 'string') throw 'Component path must be a string.';

  var scopeArray = componentName.split(':'),
      len, element, sub;
  if (scopeArray.length != 2) throw 'Path does not include a component.';

  var scope = this.scope['/'],
      scopeName = scopeArray[1];

  scopeArray = scopeArray[0].split('/');
  len = scopeArray.length;

  for (var i = 0; i <= len; i++) {
    element = scopeArray[i];
    if (element === '') continue;

    sub = scope.subScopes[element];

    if (sub) scope = sub;
    else if (i === len) {
      this.fragment = scope.components;
      this.field = scopeName;
      this.focus = scope.components[scopeName] = func;
    }
    else throw 'Scope path is invalid';
  };

  return this;
};

Viziion.prototype.returnComponent = function (componentName, callback) {
  if (typeof componentName !== 'string') throw 'Component path must be a string.';

  var scopeArray = componentName.split(':'),
      len, element, sub;
  if (scopeArray.length != 2) throw 'Path does not include a component.';

  var scope = this.scope['/'],
      scopeName = scopeArray[1];

  scopeArray = scopeArray[0].split('/');
  len = scopeArray.length;

  for (var i = 0; i <= len; i++) {
    element = scopeArray[i];
    if (element === '') continue;
    sub = scope.subScopes[element]

    if (i === len) callback(scope.components[scopeName]);
    else if (sub) scope = sub;
    else throw 'Scope path is invalid';
  }
};

Viziion.prototype.addHook = function (hook, func) {
  if (typeof hook !== 'string') throw 'Hook name must be a string.';
  this.fragment = null;
  this.field = hook;
  this.focus = this.hooks[hook] = func;
  return this;
};

Viziion.prototype.inject = function (dependancyArray) {
  if (!dependancyArray) return;

  var dependencies = [],
      len = dependancyArray.length,
      element;

  function push (dep) { dependencies.push(dep); }

  for (var i = 0; i < len; i++) {
    element = dependancyArray[i];
    this.returnComponent(element, push);
  }

  var focus = this.focus,
      fragment = this.fragment,
      field = this.field,
      hook = function hook () {
        return this.apply(null, arguments);
      }, func;

  dependencies.unshift(focus);
  func = Function.prototype.bind.apply(hook, dependencies);

  if (fragment) fragment[field] = func;
  else this.hooks[field] = func;

  return this;
};

Viziion.prototype.returnUserHandle = function () { return this.hooks; };

/* JSON HTML Generator - A Simple Library Using Viziion */

var JHTML = new Viziion('JHTML');

JHTML.addScope('/generate');

JHTML.addComponent('/generate:jsonInput', [{
  tag: '!DOCTYPE html'
}, {
  tag: 'html',
  children: [{
    tag: 'head',
    children: []
  }, {
    tag: 'body',
    children: []
  }]
}]);

JHTML.addComponent('/generate:process', function (nodes) {
  return (function build (struct, nodes) {
    var length = nodes.length, node, tag;

    for (var i = 0; i < length; i++) {
      node = nodes[i];
      tag = node.tag;

      if (!tag) throw '[JHTML] Bad syntax: Tag type is not defined on node.';

      struct.push('<' + tag + '>');

      if (node.children) {
        build(struct, node.children)
        struct.push('</' + tag + '>');
      }
    }

    return struct;
  }([], nodes));
}).inject(['/generate:jsonInput']);

JHTML.addHook('generate', function (jsonInput, process) {
  return process(jsonInput);
}).inject(['/generate:jsonInput', '/generate:process']);


var handle = JHTML.returnUserHandle();

console.log(JHTML);

/* HTML Generator Syntax - Client */

console.log(handle.generate());
Hide result
+2

Source: https://habr.com/ru/post/1619643/


All Articles