Когда бы вы использовали оператор возврата в закрытии Javascript? - PullRequest
1 голос
/ 10 сентября 2011

Рассмотрим этот первый фрагмент Javascript, который использует только var, и это для объявления области действия:

var Bro = function() {
    var self = this;
    this.storyName = "story"; // public
    var storyType = "cool"; // private

    // private function
    var composeStory  = function() {
        return storyType + ' ' + self.storyName;
    };

    // privileged function
    this.tellStory = function() {
        console.log(composeStory() + ' bro!');
    };
};

По сравнению с этим, который использует оператор возврата и несколько изменяет область действия:

var Bro = function() {
    var self = this;
    this.storyName = "story"; // private?
    var storyType = "cool"; // private

    // private function
    var composeStory = function() {
        return storyType + ' ' + self.storyName;
    };

    // privileged variables/functions
    return {
        storyName: this.storyName,
        tellStory: function() {
            console.log(composeStory() + ' bro!');
        }
    };
}

Мой вопрос:

  1. Когда вы будете использовать второй метод вместо первого, или это просто стилистическая вещь?
  2. Почему this.storyName во второмпример private, хотя я установил его на this?
  3. Мне пришлось объявить var self = this;, чтобы получить доступ к области действия this внутри обеих приватных функций.Как структуры Javascript делают объект this доступным внутри их функций?
  4. Во втором примере свойство storyName в операторе return может правильно обращаться к области действия this.Почему он может это сделать, когда не может приватная функция?

Ответы [ 3 ]

0 голосов
/ 10 сентября 2011

Вопрос 4. В JS this имеет область действия, а не область блока.

Таким образом, во втором примере в функции composeStory, this имеет область действия функции composeStory, а не область экземпляра объекта Bro. Следовательно, вы должны были сохранить this как self, потому что значение this изменилось.

(На самом деле, в функции composeStory, this обычно будет window или в строгом режиме undefined. Если вы вставите

alert(this === window); 

в функции composeStory, она выдаст «true». Если вы вставите

"use strict"; 
alert(typeof this === "undefined"); 

он снова выдаст предупреждение "истина". Подробнее здесь .)

В операторе возврата второго примера this не находится внутри функции. Так что this по-прежнему ссылается на содержащую функцию, а именно на экземпляр Bro, который создается.

0 голосов
/ 10 сентября 2011

В Javascript не существует таких понятий, как "приватный" и "публичный".То, что вы видите, - это разница между свойствами объекта и захваченными переменными замыкания.Переменные захвата замыкания могут использоваться для скрытия состояния, но они скрывают его в другом объекте, прикрепленном к функциям, созданным в области замыкания, а не в возвращаемом объекте, как в других языках.Имея это в виду, я отвечу на ваши вопросы,

1) Я бы не стал использовать ни одну форму, но они стилистически похожи, оба используют захват закрытия.Обратите внимание, однако, что первый использует шаблон конструктора, а второй использует фабричный шаблон.Первый будет работать только в том случае, если вы используете ключевое слово new до вызова Bro, второй будет игнорировать объект, созданный new, в пользу объекта, созданного литералом объекта, но вы можете безопасно вызывать его без добавления префикса new.

2) storyName не является закрытым, оно задано для другого объекта.Когда вызывается функция с префиксом new, создается новый объект, который передается как параметр this.Это объект, который вы устанавливаете "this.storyName".Этот объект затем отбрасывается в пользу объекта, который вы создаете в литерале.Вы не видите storyName, потому что он не был установлен для возвращаемого объекта.

3) Вы можете записать это в переменную замыкания, такую ​​как self, или использовать bind для функции, чтобы связать это с оригинальным this.Я предпочитаю захват закрытия самостоятельно.

4) Это все еще находится в области видимости, потому что вы выполняете в функции конструктора.

0 голосов
/ 10 сентября 2011

Я отвечу на третий вопрос.Они используют методы call и apply, доступные для всех функций, которые принимают первый аргумент в качестве контекста, в котором должна выполняться функция.

this.message = "hello ";
var function(argument) {
    console.log(this.message + argument);
}
function.call(this, "world!");
function.apply(this, ["world!"]);

Для более краткого примера см. Источник jQuery.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...