Хорошим местом для начала является JavaDocs . Они охватывают это:
Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
- Вызов метода экземпляра нулевого объекта.
- Доступ или изменение поля нулевого объекта.
- Выполнение длины null, как если бы это был массив.
- Доступ или изменение слотов с нулевым значением, как если бы это был массив.
- Бросать нуль, как если бы это было значение Throwable.
Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.
Также, если вы попытаетесь использовать нулевую ссылку с
synchronized
, который также выдаст это исключение, за JLS :SynchronizedStatement: synchronized ( Expression ) Block
- В противном случае, если значение выражения равно null,
NullPointerException
.Как это исправить?
Итак, у вас есть
NullPointerException
. Как вы это исправите? Возьмем простой пример, который выдаетNullPointerException
:public class Printer { private String name; public void setName(String name) { this.name = name; } public void print() { printString(name); } private void printString(String s) { System.out.println(s + " (" + s.length() + ")"); } public static void main(String[] args) { Printer printer = new Printer(); printer.print(); } }
Идентифицирует нулевые значения
. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:
Exception in thread "main" java.lang.NullPointerException at Printer.printString(Printer.java:13) at Printer.print(Printer.java:9) at Printer.main(Printer.java:19)
Здесь мы видим, что исключение выбрано в строке 13 (в методе
printString
). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, чтоs
имеет значение null, а вызов методаlength
на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когдаs.length()
удаляется из метода.Трассировка, где эти значения взяты из
Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что
s
передается сprintString(name)
в методеprint()
, аthis.name
- null.Трассировка, где эти значения должны быть установлены
Где установлен
this.name
? В методеsetName(String)
. С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. Этого достаточно, чтобы дать нам решение: добавить вызов
printer.setName()
перед вызовомprinter.print()
.Другие исправления
Переменная может иметь значение по умолчанию (и
setName
может помешать ему установить значение null):private String name = "";
Либо метод
printString
может проверить значение null например:printString((name == null) ? "" : name);
Или вы можете создать класс, чтобы
name
всегда имел ненулевое значение :public class Printer { private final String name; public Printer(String name) { this.name = Objects.requireNonNull(name); } public void print() { printString(name); } private void printString(String s) { System.out.println(s + " (" + s.length() + ")"); } public static void main(String[] args) { Printer printer = new Printer("123"); printer.print(); } }
См. также:
Я все еще не могу найти проблему
Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).
Даниэль, удивительное объяснение! Несколько слов по этому и хорошему списку указателя контекста выполнения this
в случае обработчиков событий.
В двух словах this
в JavaScript указывает объект, у которого (или из контекста выполнения которого) текущая функция была запущена, и она всегда доступна только для чтения, вы все равно не можете ее установить (такая попытка закончится сообщением «Недопустимая левая сторона в присваивании».
Для обработчиков событий: встроенный обработчики событий, такие как <element onclick="foo">
, переопределяют любые другие обработчики, прикрепленные ранее и раньше, поэтому будьте осторожны, и лучше не вмешиваться в встроенное делегирование событий. И благодаря Заре Алавердян, которая вдохновила меня на этот список примеров через несогласие обсуждение:)
el.onclick = foo; // in the foo - obj
el.onclick = function () {this.style.color = '#fff';} // obj
el.onclick = function() {doSomething();} // In the doSomething -
Window
el.addEventListener('click',foo,false) // in the foo - obj
el.attachEvent('onclick, function () { // this }') // window, all the
compliance to IE :)
<button onclick="this.style.color = '#fff';"> // obj
<button onclick="foo"> // In the foo - window, but you can <button
onclick="foo(this)">
Значение «this» зависит от «контекста», в котором выполняется функция. Контекстом может быть любой объект или глобальный объект, т. Е. Окно.
Таким образом, семантика «этого» отличается от традиционных языков ООП. И это вызывает проблемы: 1. когда функция передается другой переменной (скорее всего, обратный вызов); и 2. когда замыкание вызывается из метода-члена класса.
В обоих случаях это устанавливается в окно.
Поскольку этот поток наткнулся, я собрал несколько точек для новых читателей в this
.
this
? Мы используем это подобно тому, как мы используем местоимения в естественных языках, таких как английский: «Джон работает быстро, потому что он пытается поймать поезд». Вместо этого мы могли бы написать «... Джон пытается поймать поезд ».
var person = {
firstName: "Penelope",
lastName: "Barrymore",
fullName: function () {
// We use "this" just as in the sentence above:
console.log(this.firstName + " " + this.lastName);
// We could have also written:
console.log(person.firstName + " " + person.lastName);
}
}
this
не присваивается значение, пока объект не вызовет функцию, в которой он определен. В глобальной области действия все глобальные переменные и функции определяются на объекте window
. Следовательно, this
в глобальной функции относится к (и имеет значение) глобальный объект window
.
Когда use strict
, this
в глобальном и в анонимных функциях, не связанных с каким-либо объектом, имеет значение undefined
.
Ключевое слово this
g0] наиболее непонятно , когда: 1) мы используем метод, который использует this
, 2) мы назначаем метод, который использует this
для переменной, 3) функция, которая использует this
, передается как функция обратного вызова и 4) this
используется внутри замыкания - внутренней функции. (2)
[/g10]
Определено в сценарии ECMA 6 , стрелка- функции принимают привязку this
из охватывающей (функциональной или глобальной) области.
function foo() {
// return an arrow function
return (a) => {
// `this` here is lexically inherited from `foo()`
console.log(this.a);
};
}
var obj1 = { a: 2 };
var obj2 = { a: 3 };
var bar = foo.call(obj1);
bar.call( obj2 ); // 2, not 3!
Хотя функции-стрелки предоставляют альтернативу использованию bind()
, важно отметить, что они по существу отключают традиционный механизм this
в пользу более широкого понимания лексического охвата. (1)
Ссылки:
«Это» - все о сфере охвата. Каждая функция имеет свою собственную область действия, и поскольку все в JS является объектом, даже функция может хранить некоторые значения в себе, используя «this».
$('#a').click(function(){
console.log($(this).attr('href'));
});
this
- одна из неправильно понятых концепций в JavaScript, потому что она ведет себя совсем не так, как с места на место. Просто this
ссылается на «владельца» функции, которую мы сейчас выполняем.
this
помогает получить текущий объект (контекст выполнения a.k.a.), с которым мы работаем. Если вы понимаете, в каком объекте выполняется текущая функция, вы можете легко понять, что текущий this
is
var val = "window.val"
var obj = {
val: "obj.val",
innerMethod: function () {
var val = "obj.val.inner",
func = function () {
var self = this;
return self.val;
};
return func;
},
outerMethod: function(){
return this.val;
}
};
//This actually gets executed inside window object
console.log(obj.innerMethod()()); //returns window.val
//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val
console.log(obj.outerMethod()); //returns obj.val
Выше мы создаем 3 переменные с одинаковым именем «val». Один в глобальном контексте, один внутри obj и другой внутри innerMethod obj. JavaScript разрешает идентификаторы в определенном контексте, поднимая цепочку областей действия из локального глобального.
Несколько мест, где this
можно дифференцировать
var status = 1;
var helper = {
status : 2,
getStatus: function () {
return this.status;
}
};
var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2
var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1
Когда line1, JavaScript устанавливает контекст выполнения (EC) для вызова функции, устанавливая this
объекту, на который ссылается все, что было до последнего «.». поэтому в последней строке вы можете понять, что a()
был выполнен в глобальном контексте, который является window
.
this
можно использовать для ссылки на создаваемый объект
function Person(name){
this.personName = name;
this.sayHello = function(){
return "Hello " + this.personName;
}
}
var person1 = new Person('Scott');
console.log(person1.sayHello()); //Hello Scott
var person2 = new Person('Hugh');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined
Когда выполняется новый Person()
, создается совершенно новый объект. Вызывается Person
и его this
установлен для ссылки на этот новый объект.
function testFunc() {
this.name = "Name";
this.myCustomAttribute = "Custom Attribute";
return this;
}
var whatIsThis = testFunc();
console.log(whatIsThis); //window
var whatIsThis2 = new testFunc();
console.log(whatIsThis2); //testFunc() / object
console.log(window.myCustomAttribute); //Custom Attribute
Если мы пропустим ключевое слово new
, whatIsThis
ссылается на самый глобальный контекст, он может найти (window
)
Если обработчик события является встроенным, this
ссылается на глобальный объект
<script type="application/javascript">
function click_handler() {
alert(this); // alerts the window object
}
</script>
<button id='thebutton' onclick='click_handler()'>Click me!</button>
При добавлении обработчика событий через JavaScript, this
относится к элементу DOM, который генерирует событие.
.apply()
.call()
и .bind()
var that = this
в JavaScript «Это» - все о сфере видимости. Каждая функция имеет свою собственную область действия, и поскольку все в JS является объектом, даже функция может хранить некоторые значения в себе, используя «это». ООП 101 учит, что «это» применимо только к экземплярам объекта. Поэтому каждый раз, когда выполняет функция, новый «экземпляр» этой функции имеет новое значение «this».
Большинство людей путаются, когда пытаются использовать «это» внутри анонимных функций закрытия например:
(function(value) { this.value = value; $('.some-elements').each(function(elt){ elt.innerHTML = this.value; // uh oh!! possibly undefined }); })(2);
Итак, внутри each (), «this» не содержит «значение», которое вы ожидаете от него (от
this.value = value;над ним). Итак, чтобы справиться с этой проблемой (без каламбуры), разработчик мог:
(function(value) { var self = this; // small change self.value = value; $('.some-elements').each(function(elt){ elt.innerHTML = self.value; // phew!! == 2 }); })(2);
попробовать; вам понравится эта схема программирования
this
не имеет ничего общего с областью видимости. Кроме того, он имеет смысл также в функциях, которые не являются свойствами объектов.
– Bergi
8 December 2012 в 22:59
this
не ВСЕ о сфере видимости. Это ВСЕ о контексте выполнения, который не является тем же, что и область. JavaScript лексически ограничен (подразумевается, что область определяется местоположением кода), но this
определяется тем, как вызывается функция, содержащая его, а не где эта функция.
– Scott Marcus
16 March 2016 в 06:00
Вероятно, самая подробная и всесторонняя статья на this
такова:
Нежное объяснение ключевого слова этого «this» в JavaScript
Идея позади this
заключается в понимании того, что типы вызова функции имеют важное значение при установке значения this
.
Когда возникают проблемы с идентификацией this
, не спрашивайте себя:
Где
this
взято из ?, но спросите себя:
Как вызывается функция ?
arrow function (специальный случай прозрачности контекста) спросите себя:
Какое значение имеет
this
, где определена функция стрелки ?Этот настрой правилен при работе с
this
и избавит вас от головной боли.
Здесь является одним из хороших источников this
в JavaScript
.
Вот сводка:
this
является объектом window
<script type="text/javascript">
console.log(this === window); // true
var foo = "bar";
console.log(this.foo); // "bar"
console.log(window.foo); // "bar"
В node
с использованием repl, this
- это верхнее пространство имен. Вы можете ссылаться на него как global
. >this
{ ArrayBuffer: [Function: ArrayBuffer],
Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
...
>global === this
true
В node
, выполняемом из сценария, this
в глобальной области запускается как пустой объект. Это не то же самое, что global
\\test.js
console.log(this); \\ {}
console.log(this === global); \\ fasle
За исключением случаев обработчиков событий DOM или когда предоставляется thisArg
(см. ниже), как в узле, так и в браузере с использованием this
в функции, которая не вызывается с new
, ссылается на глобальную область ...
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis();
console.log(this.foo); //logs "foo"
</script>
Если вы используете use strict;
, в котором case this
будет undefined
<script type="text/javascript">
foo = "bar";
function testThis() {
"use strict";
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis(); //Uncaught TypeError: Cannot set property 'foo' of undefined
</script>
Если вы вызываете функцию с new
, this
будет новым контекстом, он не будет ссылаться на глобальный this
.
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
new testThis();
console.log(this.foo); //logs "bar"
console.log(new testThis().foo); //logs "foo"
</script>
Функции, которые вы создаете, становятся объектами функции. Они автоматически получают специальное свойство prototype
, которое вы можете присвоить значениям. Когда вы создаете экземпляр, вызывая функцию с помощью new
, вы получаете доступ к значениям, присвоенным свойству prototype
. Вы получаете доступ к этим значениям с помощью this
.
function Thing() {
console.log(this.foo);
}
Thing.prototype.foo = "bar";
var thing = new Thing(); //logs "bar"
console.log(thing.foo); //logs "bar"
Обычно ошибка заключается в назначении массивов или объектов на prototype
. Если вы хотите, чтобы экземпляры каждого имели свои собственные массивы, создайте их в функции, а не в прототипе.
function Thing() {
this.things = [];
}
var thing1 = new Thing();
var thing2 = new Thing();
thing1.things.push("foo");
console.log(thing1.things); //logs ["foo"]
console.log(thing2.things); //logs []
Вы можете использовать this
в любой функции объекта ссылаться на другие свойства этого объекта. Это не то же самое, что и экземпляр, созданный с помощью new
.
var obj = {
foo: "bar",
logFoo: function () {
console.log(this.foo);
}
};
obj.logFoo(); //logs "bar"
В обработчике событий HTML DOM this
всегда ссылается на элемент DOM, событие было присоединено к
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick);
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs "<div id="foo"></div>"
}
var listener = new Listener();
document.getElementById("foo").click();
Если вы не bind
контекст
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick.bind(this));
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs Listener {handleClick: function}
}
var listener = new Listener();
document.getElementById("foo").click();
Внутри атрибутов HTML, в которые вы можете поместить JavaScript, this
является ссылкой на элемент.
<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
Вы можете использовать eval
для доступа к this
.
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
eval("console.log(this.foo)"); //logs "bar"
}
var thing = new Thing();
thing.logFoo();
Вы можете использовать with
, чтобы добавить this
в текущую область действия, чтобы читать и записывать значения на this
, явно не ссылаясь на this
.
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
with (this) {
console.log(foo);
foo = "foo";
}
}
var thing = new Thing();
thing.logFoo(); // logs "bar"
console.log(thing.foo); // logs "foo"
jQuery во многих местах имеет this
ссылается на элемент DOM.
<div class="foo bar1"></div>
<div class="foo bar2"></div>
<script type="text/javascript">
$(".foo").each(function () {
console.log(this); //logs <div class="foo...
});
$(".foo").on("click", function () {
console.log(this); //logs <div class="foo...
});
$(".foo").each(function () {
this.click();
});
</script>
Это лучшее объяснение, которое я видел. Понимать JavaScripts это с помощью Clarity
Ссылка эта ALLWAYS означает (и содержит значение) объект - особый объект - и он обычно используется внутри функции или метода, хотя он может использоваться вне функции в глобальной области. Обратите внимание, что когда мы используем строгий режим, это содержит значение неопределенных в глобальных функциях и анонимных функциях, которые не привязаны к какому-либо объекту.
Существуют четыре условия, в которых это может запутать:
- Когда мы передаем метод (который использует этот ) в качестве параметра, который будет использоваться в качестве функции обратного вызова.
- Другой пример, когда это неправильно понимается, - это когда мы используем внутренний метод (замыкание). Важно отметить, что закрытие не может получить доступ к переменной этой внешней функции внешней функции], используя это ключевое слово, потому что эта переменная доступна только самой функции, а не внутренними функциями.
- Используя этот , когда метод присваивается переменной. Значение этого привязано к другому объекту, если мы назначим метод, который использует это для переменной
- Используя этот при использовании bind, apply и
Он дает примеры кода, объяснения и исправления кода, которые, как я думал, очень полезны.
В псевдоклассических терминах многие лекции учат ключевое слово «this» как объект, созданный конструктором класса или объекта. Каждый раз, когда новый объект строится из класса, представьте, что под капотом создается и возвращается локальный экземпляр «этого» объекта. Я помню, как он учил так:
function Car(make, model, year) {
var this = {}; // under the hood, so to speak
this.make = make;
this.model = model;
this.year = year;
return this; // under the hood
}
var mycar = new Car('Eagle', 'Talon TSi', 1993);
// ========= under the hood
var this = {};
this.make = 'Eagle';
this.model = 'Talon TSi';
this.year = 1993;
return this;
это использование для Scope так же, как это
<script type="text/javascript" language="javascript">
$('#tbleName tbody tr').each(function{
var txt='';
txt += $(this).find("td").eq(0).text();
\\same as above but synatx different
var txt1='';
txt1+=$('#tbleName tbody tr').eq(0).text();
alert(txt1)
});
</script>
значение txt1 и txt одинаково в вышеприведенном примере $ (this) = $ ('# tbleName tbody tr') является Same
Каждая функция контекста выполнения в javascript имеет контекст контекста этот параметр , который задается:
Каким бы ни был этот контекст области видимости, ссылается на «this».
Вы можете изменить это значение для параметра этого контекста области , используя func.call
, func.apply
или func.bind
.
По умолчанию и что сбивает с толку большинство новичков, когда вызывающий вызывающий вызов вызывается после того, как событие добавлено в элемент DOM, контекст области это значение функции является элементом DOM.
jQuery делает это тривиальным для изменения с помощью jQuery.proxy.
this
в Javascript, заключается в том, что не является внутренним свойством самой функции, а скорее артефактом способа вызова функции.
– Pointy
27 June 2010 в 15:34
func.call
, func.bind
и т. д. - Sushil
– Sushil
25 June 2013 в 11:04
this
делает not i> ссылку на область функции. this
будет ссылаться на конкретный объект (или, возможно, undefined
), который, как вы сказали, может быть изменен с помощью .call()
или .apply()
. scope i> функции (по сути, при упрощении), к каким переменным он имеет доступ, и это полностью зависит от того, где функция объявлена и не может быть изменена.
– nnnnnn
3 January 2015 в 23:48
this
и область не имеют ничего общего друг с другом в ES5 и ранее (например, когда этот ответ был написано). В ES2015 (aka ES6), this
и область действия связаны с one i> довольно минимальным способом по стрелочным функциям (функция this
в функции стрелки наследуется из своей охватывающей области), но this
никогда относится к сфере действия.
– T.J. Crowder
14 November 2015 в 16:09
this
в Javascript всегда ссылается на «владельца» выполняемой функции.
Если явный владелец не определен, то ссылается на самый верхний владелец - объект окна.
Итак, если бы я сделал
function someKindOfFunction() {
this.style = 'foo';
}
element.onclick = someKindOfFunction;
this
, он ссылался бы на объект элемента. Но будьте осторожны, многие люди делают эту ошибку
<element onclick="someKindOfFunction()">
В последнем случае вы просто ссылаетесь на функцию, а не передаете ее элементу. Поэтому this
будет ссылаться на объект окна.
Может ли помочь этому ? (Большая путаница «этого» в javascript исходит из того факта, что он вообще не связан с вашим объектом, а с текущей исполняемой областью - это может быть не совсем так, как это работает, но для меня это всегда так, см. статью для полного объяснения)
Трудно получить хорошее представление о JS или написать больше, чем что-либо тривиальное в нем, если вы не понимаете его полностью. Вы не можете просто позволить себе быстро окунуться :) Я думаю, что лучший способ начать работу с JS - сначала посмотреть эти видео-лекции Дугласа Крокфорда - http://yuiblog.com/crockford/ , который охватывает это и то, и все остальное о JS.
Немного информации об этом ключевом слове
Давайте перечислим ключевое слово this
на консоль в глобальной области без кода, но
console.log(this)
В Client / Browser this
] - глобальный объект, который является window
console.log(this === window) // true
и
В ключевом слове Server / Node / Javascript this
также является глобальным объектом, который является module.exports
console.log(this === module.exports) // true
console.log(this === exports) // true
Имейте в виду, что exports
- это просто ссылка на module.exports