Как “это” ключевое слово работает в функции?

В Java все переменные, которые вы объявляете, на самом деле являются «ссылками» на объекты (или примитивы), а не самими объектами.

При попытке выполнить один метод объекта , ссылка просит живой объект выполнить этот метод. Но если ссылка ссылается на NULL (ничего, нуль, void, nada), то нет способа, которым метод будет выполнен. Тогда runtime сообщит вам об этом, выбросив исключение NullPointerException.

Ваша ссылка «указывает» на нуль, таким образом, «Null -> Pointer».

Объект живет в памяти виртуальной машины пространство и единственный способ доступа к нему - использовать ссылки this. Возьмем этот пример:

public class Some {
    private int id;
    public int getId(){
        return this.id;
    }
    public setId( int newId ) {
        this.id = newId;
    }
}

И в другом месте вашего кода:

Some reference = new Some();    // Point to a new object of type Some()
Some otherReference = null;     // Initiallly this points to NULL

reference.setId( 1 );           // Execute setId method, now private var id is 1

System.out.println( reference.getId() ); // Prints 1 to the console

otherReference = reference      // Now they both point to the only object.

reference = null;               // "reference" now point to null.

// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );

// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...

Это важно знать - когда больше нет ссылок на объект (в пример выше, когда reference и otherReference оба указывают на null), тогда объект «недоступен». Мы не можем работать с ним, поэтому этот объект готов к сбору мусора, и в какой-то момент VM освободит память, используемую этим объектом, и выделит другую.

248
задан rmeador 30 September 2016 в 02:56
поделиться

4 ответа

Снятый части с одной машины для ремонта других из другого моего сообщения, вот больше, чем Вы когда-нибудь хотели знать [приблизительно 1 110] это .

, Прежде чем я запущу, вот самая важная вещь иметь в виду о JavaScript и повториться себе, когда это не имеет смысла. JavaScript не имеет классов (ES6 class синтаксический сахар ). Если что-то похоже на класс, это - умный прием. JavaScript имеет объекты и функции . (это не на 100% точно, функции являются просто объектами, но может иногда быть полезно думать о них как об отдельных вещах)

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

существует четыре способа вызвать функции в JavaScript. Можно вызвать функцию как метод , как функция , как , конструктор , и с [1 116] подает заявку .

Как Метод

метод А является функцией, это присоединено к объекту

var foo = {};
foo.someMethod = function(){
    alert(this);
}

, Когда вызвано как метод, это будет связано с объектом, которого функция/метод является частью. В этом примере это будет связано с нечто.

Как Функция

, Если у Вас есть одинокая функция, этот , переменная будет связана с "глобальным" объектом, почти всегда объект окна в контексте браузера.

 var foo = function(){
    alert(this);
 }
 foo();

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

Многие люди обходят проблему путем выполнения чего-то как, гм, это

var foo = {};
foo.someMethod = function (){
    var that=this;
    function bar(){
        alert(that);
    }
}

Вы определяете переменную , что , который указывает на [1 121] это . Закрытие (тема все свои собственные) сохраняет , что вокруг, поэтому при вызове панели как обратного вызова это все еще имеет ссылку.

ПРИМЕЧАНИЕ: В use strict режим, если используется, поскольку функция, this не связывается с глобальным. (Это undefined).

Как Конструктор

можно также вызвать функцию как конструктор. На основе соглашения о присвоении имен Вы используете (TestObject), это также может быть тем, что Вы делаете, и то, что смещается Вы .

Вы вызываете функцию как Конструктор с новым ключевым словом.

function Foo(){
    this.confusing = 'hell yeah';
}
var myObject = new Foo();

, Когда вызвано как конструктор, новый Объект будет создан, и это будет связано с тем объектом. Снова, если у Вас будут внутренние функции, и они используются в качестве обратных вызовов, Вы будете вызывать их как функции, и это будет связано с глобальным объектом. Используйте тот var это = этот прием/шаблон.

Некоторые люди думают, ключевое слово конструктора / новое ключевое слово были костью, брошенной в программистов ООП Java / традиционных программистов ООП как способ создать что-то подобное классам.

С Применять Методом

Наконец, каждая функция имеет метод (да, функции являются объектами в JavaScript), названный, "применяются". Подайте заявку позволяет Вам определить то, чем значением [1 125] это будет, и также позволяет Вам передать в массиве аргументов. Вот бесполезный пример.

function foo(a,b){
    alert(a);
    alert(b);
    alert(this);
}
var args = ['ah','be'];
foo.apply('omg',args);
557
ответ дан Uwe Keim 23 November 2019 в 02:59
поделиться

Вызовы функции

Функции являются просто типом Объекта.

Все Функциональные объекты имеют , вызов и применяется методы, которые выполняют Функциональный объект, к ним обращаются.

, Когда названо, первый аргумент этим методам определяет объект, на который сошлются this ключевое слово во время выполнения Функции - если это будет null или undefined, глобальный объект, window, используется для [1 112].

Таким образом, вызывая Функцию...

whereAmI = "window";

function foo()
{
    return "this is " + this.whereAmI + " with " + arguments.length + " + arguments";
}

... с круглыми скобками - foo() - эквивалентно [1 114] или foo.apply(undefined), который является эффективно то же как [1 116] или foo.apply(window).

>>> foo()
"this is window with 0 arguments"
>>> foo.call()
"this is window with 0 arguments"

Дополнительные аргументы [1 118] передаются как аргументы вызову функции, тогда как единственный дополнительный аргумент [1 119] может определить аргументы в пользу вызова функции как подобный Массиву объект.

Таким образом, foo(1, 2, 3) эквивалентно [1 121] или foo.apply(null, [1, 2, 3]).

>>> foo(1, 2, 3)
"this is window with 3 arguments"
>>> foo.apply(null, [1, 2, 3])
"this is window with 3 arguments"

, Если функция является свойством объекта...

var obj =
{
    whereAmI: "obj",
    foo: foo
};

... доступ к ссылке на Функцию через объект и вызов его с круглыми скобками - obj.foo() - эквивалентен [1 124] или foo.apply(obj).

Однако функции, сохраненные, поскольку, свойства объектов не "связываются" с теми объектами. Как Вы видите в определении obj выше, так как Функции являются просто типом Объекта, на них можно сослаться (и таким образом может быть передан в отношении Вызова функции или возвращен ссылкой из Вызова функции). То, когда ссылка на Функцию передается, никакая дополнительная информация о том, откуда она была передана [1 144], несут с ним, который является, почему следующее происходит:

>>> baz = obj.foo;
>>> baz();
"this is window with 0 arguments"

вызов к нашей Ссылке на функцию, baz, не обеспечивает контекста для вызова, таким образом, это - эффективно то же как [1 128], таким образом this заканчивает тем, что сослался window. Если мы хотим baz знать, что это принадлежит [1 132], мы должны так или иначе предоставить ту информацию, когда baz назван, который является, где первый аргумент [1 134] или apply и закрытия играет роль.

цепочки Объема

function bind(func, context)
{
    return function()
    {
        func.apply(context, arguments);
    };
}

, Когда Функция выполняется, она создает новый объем и имеет ссылку на любой объем включения. Когда анонимная функция создается в вышеупомянутом примере, она имеет ссылку на объем, в котором она была создана, который является bind объем. Это известно как "закрытие".

[global scope (window)] - whereAmI, foo, obj, baz
    |
    [bind scope] - func, context
        |
        [anonymous scope]

, Когда Вы пытаетесь получить доступ к переменной, эта "цепочка объема" обойдена для нахождения переменной с именем - если текущая область не содержит переменную, Вы смотрите на следующий объем в цепочке, и так далее пока Вы не достигаете глобальной области видимости. Когда анонимная функция возвращается и bind выполнение концов, анонимная функция все еще имеет ссылку на [1 138] объем, таким образом bind объем не "уходит".

, Учитывая все вышеупомянутое необходимо теперь быть в состоянии понять, как объем работает в следующем примере, и почему техника для того, чтобы раздать функцию "предварительно связала" с конкретным значением [1 140], это будет иметь, когда это назовут работами:

>>> baz = bind(obj.foo, obj);
>>> baz(1, 2);
"this is obj with 2 arguments"
35
ответ дан Jonny Buchanan 23 November 2019 в 02:59
поделиться

это - определенное поведение? Это - безопасный перекрестный браузер?

Да. И да.

там любое обоснование, базовое, почему это - способ, которым это...

значение this довольно просто вывести:

  1. , Если this используется в функции конструктора, и функция была вызвана с new, ключевое слово, this относится к объекту, который будет создан. this продолжит означать объект даже в открытых методах.
  2. , Если this используется где-нибудь еще, включая вложенный , защитил функции, это относится к глобальной области видимости (который в случае браузера является объектом окна).

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

9
ответ дан Rakesh Pai 23 November 2019 в 02:59
поделиться

В этом случае внутреннее this связывается с глобальным объектом вместо к this переменная внешней функции. Это - способ, которым разработан язык.

См. "JavaScript: Хорошие Части" Douglas Crockford для хорошего объяснения.

4
ответ дан Santiago Cepas 23 November 2019 в 02:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: