Как ссылки на переменные на внешние области из экземпляра объекта работают в NodeJS - PullRequest
0 голосов
/ 07 января 2019

Я немного сбит с толку относительно того, как область видится внутренними объектами / связана с ними. Я понимаю, что область действия определяет, как переменные заключаются / видимы, и что контекст ссылается на создание и привязку этого к объекту, и что внутренние объекты и функции имеют доступ к глобальному объекту; Однако я не понимаю, как (или если) сфера относится к объектам.

  1. Как работает обзор под капотом?
  2. Являются ли единственные способы доступа к внешней переменной в объекте посредством (а) связывания this, содержащего внешнюю переменную, с объектом или (б) добавления этой переменной к глобальному объекту? Или у объектов есть ссылки на внешние области, использующие область видимости javascript?

Я пытаюсь настроить веб-сервер NodeJS и хочу определить локальную переменную, к которой могут обращаться все другие внутренние объекты, созданные в файле записи (индекса). Я пытался сделать это с var x = 10; в файле ввода; тем не менее, когда я пытаюсь получить доступ к переменной из объекта, созданного позже в коде, нет никакого способа получить доступ к этой переменной. Я создал объект с помощью оператора new, затем вызвал в этом объекте метод, который регистрирует x на консоли, но я получаю ошибку «x не определен». При отладке в chrome я не могу найти x, определенный где-либо. Я вижу глобальный контекст, который представляется просто глобальным объектом, я вижу локальный контекст, который выглядит как экземпляр объекта, но при этом я не вижу ссылки на контекст, который создает экземпляр объекта. Я могу поместить переменную в глобальный объект, и тогда на нее можно будет ссылаться, но я не хочу впадать в дурную привычку помещать все в глобальный объект.

Top-Level (файл называется startup.js и вызывается с использованием node startup.js):

  var express = require('express');
  var web = express();
  var Controller = require('./classes/Controller');
  var x = 10;
  var controller = new Controller(props);
  web.post('/addEntry', function(req, res){
    controller.createEntry(req.body, (error, status) =>{
      if (error) {
          res.send('Error: ' + error);
          console.log(error);
      }
      res.send("Success:" + status);
    });
 });

 web.listen(3000);

Файл контроллера:

class Controller {
  constructor()

  createEntry(entry, callback) {
     console.log(x);
     return callback(entry);
  }
}

module.exports = Controller;
  1. Я хотел бы иметь возможность ссылаться на x из внутреннего контекста в установленном порядке, который считается хорошей практикой. Если это невозможно при использовании переменных в контекстах более высокого уровня, чем методы в экземплярах объектов, я был бы очень признателен, если бы вы могли предложить альтернативу (желательно, которая не привязывается к глобальному объекту). Спасибо за ваше время и помощь, и, пожалуйста, дайте мне знать, если и как я могу улучшить пост!

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Как работает обзор под капотом?

Область действия ограничена функцией (var) или блоком (let).

Если var находится в той же функции или let в том же блоке, вы можете получить к нему доступ.

Если ваша текущая область определена внутри области, в которой доступна переменная, вы можете получить к ней доступ, если она не замаскирована другой переменной с тем же именем в более узкой области.

Являются ли единственные способы доступа к внешней переменной в объекте посредством (а) привязки объекта this, содержащего внешнюю переменную, к объекту или (б) добавления этой переменной к глобальному объекту? Или у объектов есть ссылки на внешние области, использующие область видимости javascript?

Ваш случай (а) не будет обращаться к переменной. Свойства объекта не являются переменными.

Ваш случай (b) означает, что переменная хранится в самой широкой области видимости. Глобалы лучше избегать. Держите области видимости как можно более узкими. Это облегчает управление кодом.

Я хотел бы иметь возможность ссылаться на х из внутренней области видимости в установленном порядке, который считается хорошей практикой.

Передать значение x в качестве аргумента функции. Не пытайтесь получить доступ к x напрямую.

0 голосов
/ 07 января 2019

x в вашем примере доступен только для кода в startup.js. Это не доступно нигде. Это не глобальный (который, я думаю, вы уже знаете), это глобальный модуль внутри startup.js модуля.

Чтобы сделать его доступным для кода Controller, обычно нужно передать его Controller в качестве аргумента:

var controller = new Controller(props, x);
// ------------------------------------^

Это не передает переменную, но она передает текущее значение переменной на момент выполнения этой строки кода.

Если вы хотите передать Controller что-то, что будет видеть текущее значение x, даже если вы измените его, вы поместите x в объект как свойство и передадите ссылку на объект на Controller вместо:

var stuff = {x: 10};
// ...
var controller = new Controller(props, stuff);

Controller запомнит ссылку на объект, а затем найдет x этого объекта:

class Controller {
  constructor(props, stuff) {
      this.stuff = stuff; // <====
  }

  createEntry(entry, callback) {
     console.log(stuff.x);
     // ---------^^^^^^
     return callback(entry);
  }
}

module.exports = Controller;

В качестве альтернативы, в зависимости от того, что такое x (параметр конфигурации для всей системы?): Вы можете поместить x и другие связанные с ним вещи в их собственный модуль (скажем, stuff.js):

module.exports = {x: 10};

... и иметь controller.js и все остальное, что нужно для загрузки модуля:

var stuff = require("./stuff");
// ...
class Controller {
  constructor(props) {
  }

  createEntry(entry, callback) {
     console.log(stuff.x);
     // ---------^^^^^^
     return callback(entry);
  }
}

Я думаю, что вышеизложенное отвечает на вопросы № 2 и № 3, но:

1. Как работает область видимости под капотом?

Scoping - это лексическая (текстовая) концепция, которая определяет, какие идентификаторы, et. al., доступны для кода. Области действия работают как вложенные блоки: каждая область имеет доступ ко всему в своей содержащей области. Так, например:

var x;
// Code here has access to `x`
function outer() {
    var y;

    // Code here has access to `x` and `y`

    function inner() {
        var z;

        // Code here has access to `x`, `y`, and `z`
    }

    inner();
}

outer();

Вы можете подумать: «Эй, подожди, но что, если ты позвонишь outer дважды? Тогда есть два y с!» И вы абсолютно правы, есть! А также два inner с. Каждый inner имеет доступ к одному и тому же x, но у каждого есть разные y: y, созданный для вызова outer, который создал inner.

Вот как замыкания работают. Подробнее:


Re this.x: Вы упомянули использование this для доступа к x (например, this.x). Этот механизм (this.x) ищет свойство объекта . Напротив, ваша x переменная не является свойством, это переменная. Объекты JavaScript и область видимости не имеют ничего общего друг с другом. Хотя мы часто концептуализируем область видимости как использование скрытых объектов за кулисами (спецификация, безусловно, делает это), эти объекты являются чисто концептуальными и не доступны в коде (за одним исключением: глобальный объект, который дублируется как реальный объект и контейнер для глобальных переменных, объявленных с var и глобальных объявленных функций [но не для переменных, объявленных с let или const, или классов, определенных с class]).

...