2016-06-11 2 views
0

Следующие function once (проблема 13) принимает func и возвращает функцию, которая позволяет вызывать только один раз func.Закрытие в JavaScript и выполнение функции один раз

function add(a, b) { 
    return a + b; 
} 

function once(func) { 
    return function() { 
     var f = func; 
     func = null; 
     return f.apply(this, arguments); 
    }; 
} 

add_once = once(add); 
add_once(3, 4) // 7 
add_once(3, 4) // throws 

Есть две вещи, о которых я не понимаю.

  1. Почему запись func = null не позволяет нам снова вызвать функцию? После сохранения указателя на функцию (все правильно использовать C lingo, не так ли?) В var f = func, я ожидаю, что назначение null на указатель функции func (func - это просто указатель на функцию; ?) не имеет значения, поскольку функция (указатель на) уже сохранена в f. Что мне не хватает?
  2. Я получаю, что это necessary, чтобы написать f.apply(this, arguments);, а не просто f(arguments);, потому что это один из особенностей JavaScript. Последний отправил в функцию массив, а не список аргументов. Но я не понимаю, к чему относится this. Это относится к анонимной функции во второй строке или к once? И если назначение func = null предназначено для остановки второго вызова, потому что закрытие приведет к func, который был обнулен, почему он работает в первый раз, когда он называется?

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

+0

То, как вы его вызываете, 'this' будет глобальным объектом или' undefined', если в строгом режиме. –

+0

для вашего вопроса 1: mistery - это ключевое слово "var". когда вы определяете переменную с «var», это означает игнорирование всех одинаковых значений переменной в текущей или родительской области и использование вновь назначенного значения для текущей области. поэтому второй вызов var f = func вызовет f = null. –

+0

@Tolgahan: код будет работать точно так же без 'var'. –

ответ

1

«Почему писать FUNC = нуль остановить нас от вызова функции во второй раз?»

  • , когда add_once запускается в первый раз, это шаги, которые принимаются ...

    var f = func; step1 - переменная f теперь имеет ссылку на функцию добавления, которая была передана в качестве параметра. func все еще имеет ссылку на функцию добавления, так что теперь функции func и f указывают на одну и ту же функцию добавления.

    func = null; step2 - теперь func указывает на null и больше не ссылается на функцию добавления. Но доступная f все еще имеет ссылку на функцию добавления.

    return f.apply(this,arguments); step3 - поскольку f все еще ссылается на функцию добавления, мы можем передать эту функцию массиву аргументов и сразу вызвать ее. apply немедленно вызывает функцию add с указанными аргументами. Затем мы возвращаем результат. 'this' привязан к тому, что f ссылается, в этом случае это функция добавления. Хороший трюк, который следует помнить, заключается в том, что «это» будет привязано ко всему, что находится слева от «.». на сайте вызова, где вызывается функция. В данном случае это не имеет значения. Вы также могли бы поставить нуль на свое место, и все будет хорошо.

  • когда add_once побежал во второй раз эти новые шаги ....

    var f = func; step1 - мы теперь указывают е на то, что значение функ ссылается. func все еще ссылается на null, так как мы указали func на null при первом запуске функции. Теперь f и func оба указывают на нуль.

    func = null; step2 - мы снова указываем переменную func/parameter равным null. func уже указывал на null, так что теперь func определенно указывает на null.

    return f.apply(this,arguments); step3 - здесь f все еще указывает на нуль. вы, очевидно, не можете вызвать null, поскольку значение null не является функцией. Здесь вызывается ошибка.

Надеюсь, это поможет. Мне нравится помнить, что переменная ничего не хранит, она ссылается на значение. Мне нравится думать о переменной, указывающей на значение. У вас может быть много переменных, указывающих на одно и то же значение. Переназначение переменной просто указывает эту переменную на новое значение.

1

Помните, что вы не вызывая once снова второй раз, так что, когда вы видите func используется внутри возвращаемой функции, он больше не является указатель на то, что было принято в once, поскольку возвращаемая функция изменила значение (поскольку возвращаемая функция уже была вызвана ранее), на которую ссылается переменная с именем func внутри укупорочного средства, предоставленная once, путем выражения func = null. После вызова в первый раз значение, возвращаемое внутри функции возврата, когда вы запрашиваете значение func, изменилось с исходного значения, прошедшего в once, на null.

EDIT

После прочтения, что я только что написал, хотя это имеет смысл для меня, я не могу винить вас, если это не поможет: S

EDIT # 2

Вторая часть вашего вопроса - что такое this, ссылаясь на. Это полностью зависит от того, как вы вызываете функцию, возвращаемую once. См this * вопрос

* каламбур

+1

Вы прибивали его (мое недоразумение) с помощью первых нескольких слов, но потом вы смутили чертову из меня с остальными. Я только выяснил, что происходит после прочтения ответа Диллона, поэтому я проверю его ответ и +1 ваш. – Calaf

Смежные вопросы