Исправить исключение NullReferenceException можно с помощью Null-условных операторов в c # 6 и написать меньше кода для обработки нулевых проверок.
Он используется для проверки нуля до выполнения доступа к члену (?. ) или index (? [).
Пример
var name = p?.Spouse?.FirstName;
эквивалентен:
if (p != null)
{
if (p.Spouse != null)
{
name = p.Spouse.FirstName;
}
}
В результате имя будет нулевым когда p равно null или когда p.Spouse имеет значение null.
В противном случае имени переменной будет присвоено значение p.Spouse.FirstName.
Для получения дополнительной информации: Операторы с нулевым условием
Строка setInterval должна выглядеть так: -
this.intervalID = setInterval(
(function(self) { //Self-executing func which takes 'this' as self
return function() { //Return a function in the context of 'self'
self.retrieve_rate(); //Thing you wanted to run as non-window 'this'
}
})(this),
this.INTERVAL //normal interval, 'this' scope not impacted here.
);
Изменить: тот же принцип применяется к «onload
». В этом случае его общий для «внешнего» кода делать мало, он просто устанавливает запрос, а затем отправляет его. В этом случае дополнительные накладные расходы дополнительные функции, как в приведенном выше коде, не нужны. Ваш retrieve_rate должен выглядеть следующим образом: -
retrieve_rate : function()
{
var self = this;
var ajax = new XMLHttpRequest();
ajax.open('GET', 'http://xyz.com', true);
ajax.onreadystatechanged= function()
{
if (ajax.readyState == 4 && ajax.status == 200)
{
// prefs available as self.prefs
}
}
ajax.send(null);
}
Это не решение для красоты, но оно широко используется:
var self = this;
var ajax = null;
//...
ajax.onload = function() {
self.prefs....;
}
setInterval
вызывает функцию retrieve_rate
, значение this
внутри метода относится к глобальному объекту ...
– CMS
1 May 2010 в 09:15
window.setInterval(function(){console.log(this)}.bind(this), 100)
это законно в javascript и сохраняет много кода:)
Это было бы самое чистое решение, так как большую часть времени вы действительно хотите переключить этот контекст для своих последовательных вызовов методов:
Также легче понять концепцию.
// store scope reference for our delegating method
var that = this;
setInterval(function() {
// this would be changed here because of method scope,
// but we still have a reference to that
OURMETHODNAME.call(that);
}, 200);
Поведение setInterval
по умолчанию - это привязка к глобальному контексту. Вы можете вызвать функцию-член, сохранив копию текущего контекста. Внутри retrieve_rate переменная this
будет правильно привязана к исходному контексту. Вот как выглядит ваш код:
var self = this;
this.intervalID = setInterval(
function() { self.retrieve_rate(); },
this.INTERVAL);
Бонусный совет: для простой ссылки на функцию (в отличие от ссылки на объект, которая имеет функцию-член) вы можете изменить контекст с помощью JavaScript call
или apply
.
prefs: null,
startup : function()
{
// init prefs
...
this.retrieve_rate();
var context = this;
this.intervalID = setInterval(function()
{
context.retrieve_rate();
}, this.INTERVAL);
},
retrieve_rate : function()
{
var ajax = null;
ajax = new XMLHttpRequest();
ajax.open('GET', 'http://xyz.com', true);
var context = this;
ajax.onload = function()
{
// access prefs using context.
// e.g. context.prefs
}
}
this
внутри функции, переданной в setInterval
, будет ссылаться на глобальный объект. Вы имели в виду context.retrieve_rate
вместо this.retrieve_rate
?
– CMS
1 May 2010 в 09:11
this.intervalID = setInterval(this.retrieve_rate.bind(this), this.INTERVAL);
При улучшенной поддержке браузера время теперь полезно использовать расширение EcmaScript 6, метод стрелки =>
, чтобы сохранить this
правильно.
startup : function()
{
// init prefs
...
this.retrieve_rate();
this.intervalID = setInterval( () => this.retrieve_rate(), this.INTERVAL);
},
Использование метода => сохраняет this
, когда retrieve_rate()
вызывается интервалом. Нет необходимости в напуганном себе или прохождении this
в параметрах
self
является единственным вариантом здесь? можете ли вы подтвердить, что решение Мэтью не будет работать? – Pablo 1 May 2010 в 14:03this
в качестве параметра, который был ненужным и неудобным (любой вызывающий абонентretrieve_rate
знал бы это ненужное специальное требование). – AnthonyWJones 1 May 2010 в 20:26this
в качестве аргумента(function(self){...})(this)
в setInterval не работала для меня, потому что функция выполняется немедленно, а не задерживается. Решение @Joel Fillmore для меня работает – Homan 21 January 2013 в 20:59