Несколько вопросов относительно JavaScript Constructor и анонимных функций - PullRequest
2 голосов
/ 28 августа 2009

У меня есть следующая функция JavaScript:

function Console() {
    this.Log = function(msg) {
        if (document.getElementById("console")) {
            var console = document.getElementById("console");
            console.innerHTML += msg + "<br/>";
        }
    }
}

Вопрос 1: Почему мне нужно использовать новое ключевое слово?

new Console().Log("hello world");

Почему я не мог просто сделать это?

Console().Log("hello world without using new");

Вопрос 2:

var logger = function() {
    this.log = function(msg) {
        new Console().Log(msg);
        new Console().Log("log initialized");
    }

    this.log2 = function(msg) {
        new Console().Log(msg);
        new Console().Log("log2 initialized");
    }
}(); //notice the brackets

Это не запустится из-за () в конце логгера.

new logger().log("hello world");

Я знаю, что с помощью трейлинга () это означает, что функция вызывается немедленно, но почему она не работает? Это потому, что function () {} (); нельзя присвоить другим переменным?

Ответы [ 3 ]

5 голосов
/ 28 августа 2009
  1. Ключевое слово new создает экземпляр вашего объекта Console, который затем можно вызвать методом Log. Если вы просто вызовете Console() напрямую, вы получите любое возвращаемое значение для этой функции. В вашем случае их нет, поэтому undefined. Кроме того, если вы не используете ключевое слово new, все, что вы назначите для this в этой "функции класса", будет загрязнять глобальную область видимости. Таким образом, вместо того, чтобы назначать ваши методы на this, вы должны будете использовать прокси-объект , который вы бы вместо этого вернули.

  2. В вашем примере вы присваиваете переменную logger для возвращаемого значения вызова вашей анонимной функции. Опять же, он ничего не возвращает, поэтому вызов new logger() не будет работать, потому что вы не можете создать экземпляр undefined. Таким образом, удаление конечного () из анонимной функции присвоит функции значение logger, а не ее возвращаемое значение, которое затем можно создать с помощью new. (Вы также можете использовать прокси-объект снова).

В обоих приведенных выше примерах я настоятельно рекомендую использовать ключевое слово new вместо создания и возврата прокси-объекта. Это использует преимущества встроенного в Javascript механизма создания экземпляров и цепочки прототипов функций и значительно ускоряет *1037* создания объектов.

Это сообщение в блоге Джона Резига стоит прочитать для получения дополнительной информации о том, как работает "классовая" реализация в Javascript: http://ejohn.org/blog/simple-class-instantiation/

2 голосов
/ 28 августа 2009

Ответ 1:

Вы добавили функцию «Журнал» в «это». Вот почему вы должны создать объект из консольной функции, прежде чем сможете получить к нему доступ.

Когда вы выполняете Console (). Log (), вы пытаетесь запустить консольную функцию и вызвать метод 'Log' для возвращаемого объекта. Поскольку консольная функция ничего не возвращает, она не определена и, следовательно, вы не можете получить доступ к методу Log.

Ответ 2:

«Регистратор» - это не функция, а результат вывода анонимной функции.

E.g. var logger = function() { //your code; } ();

Ваша анонимная функция ничего не возвращает, поэтому регистратор будет «неопределенным». А для неопределенного объекта не существует метода 'log'.

Чтобы решить эту проблему, сделайте следующее:

var logger = function() {
    var output = {};
    output.log = function(msg) {
        new Console().Log(msg);
        new Console().Log("log initialized");
    }

    output.log2 = function(msg) {
        new Console().Log(msg);
        new Console().Log("log2 initialized");
    }

    return output;
}();

To use, you can write,

logger.log('hello');

Основные сведения о функции и создании объектов в JS

Главное, что вам нужно понять, это то, что в JavaScript обычная функция действует как «конструктор» при вызове с ключевым словом «new».

Рассмотрим следующую функцию.

function Console()
{
    this['name'] = 'Console'
}

Когда вы вызываете вышеуказанную функцию,

   Console();
   alert(window.name); //alerts 'Console';

'this' будет объектом 'window' и добавит свойство 'name' со значением 'Console'.

Если вы вызываете вышеуказанную функцию, как,

   var output = new Console();
   alert(output.name)  // alerts 'Console'

JavaScript создаст новый объект, доступный через «this» внутри «Console». Теперь вывод будет иметь свойство name.

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

2 голосов
/ 28 августа 2009

Когда вы делаете function(){}(), вы сразу же определяете и вызываете функцию, как вы указали. Поэтому, когда у вас есть это:

var logger = function(){}();

Вы присваиваете logger для возвращаемого значения этой функции, а не самой функции. В вашем примере функция ничего не возвращает, поэтому logger будет неопределенным.

Так же, как стиль, при написании анонимных функций, которые вызываются немедленно, довольно стандартно заключать функцию в скобки:

var logger = (function() { ... })();

Это просто визуальный намек для читателя, что вы собираетесь вызывать эту функцию, и это может избавить вас от путаницы. На самом деле, в некоторых ситуациях это довольно важно: см. комментарии ниже!

...