В 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 освободит память, используемую этим объектом, и выделит другую.
Снятый части с одной машины для ремонта других из другого моего сообщения, вот больше, чем Вы когда-нибудь хотели знать [приблизительно 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);
Функции являются просто типом Объекта.
Все Функциональные объекты имеют , вызов и применяется методы, которые выполняют Функциональный объект, к ним обращаются.
, Когда названо, первый аргумент этим методам определяет объект, на который сошлются 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"
это - определенное поведение? Это - безопасный перекрестный браузер?
Да. И да.
там любое обоснование, базовое, почему это - способ, которым это...
значение this
довольно просто вывести:
this
используется в функции конструктора, и функция была вызвана с new
, ключевое слово, this
относится к объекту, который будет создан. this
продолжит означать объект даже в открытых методах. this
используется где-нибудь еще, включая вложенный , защитил функции, это относится к глобальной области видимости (который в случае браузера является объектом окна). второй случай является, очевидно, недостатком дизайна, но довольно легко работать вокруг этого при помощи закрытий.
В этом случае внутреннее this
связывается с глобальным объектом вместо к this
переменная внешней функции. Это - способ, которым разработан язык.
См. "JavaScript: Хорошие Части" Douglas Crockford для хорошего объяснения.