Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Значение в прототипе имеет поведение ключа, которое отличается от свойства, установленного непосредственно в экземпляре. Попробуйте это:
// Create a constructor
function A() {}
// Add a prototype property
A.prototype.name = "Freddy";
// Create two object instances from
// the constructor
var a = new A();
var b = new A();
// Both instances have the property
// that we created on the prototype
console.log(a.name); // Freddy
console.log(b.name); // Freddy
// Now change the property on the
// prototype
A.prototype.name = "George";
// Both instances inherit the change.
// Really they are just reading the
// same property from the prototype
// rather than their own property
console.log(a.name); // George
console.log(b.name); // George
Это было бы невозможно без прототипного наследования.
Вы можете проверить, является ли свойство свойством экземпляров или свойством прототипа, используя метод hasOwnProperty
.
console.log(a.hasOwnProperty("name")); // false
Экземпляр может переопределить значение prototype
.
b.name = "Chris";
console.log(b.hasOwnProperty("name")); // true
console.log(a.name); // George
console.log(b.name); // Chris
И вернитесь к значению prototype
.
delete b.name;
console.log(b.hasOwnProperty("name")); // false
console.log(b.name); // George
Это мощная часть прототипического наследования.
В другом шаблоне:
function A() {
this.name = "George";
}
Переменная this.name
объявляется снова с каждым новым экземпляром.
Имеет смысл иметь методы как функции, объявленные в прототипе. Вместо того, чтобы определение функции повторно объявлялось в каждом экземпляре, все экземпляры могут совместно использовать одну функцию.
С точки зрения переменных, а не функций, прототип может быть использован для значений по умолчанию в случае, когда экземпляр не устанавливает свое собственное значение.
Да, я согласен, что прототип можно использовать для значений свойств (переменных) по умолчанию. Функция конструктора не должна объявлять свойство; это может быть сделано условно.
function Person( name, age ) {
this.name = name;
if ( age ) {
this.age = age;
}
}
Person.prototype.sayHello = function() {
console.log( 'My name is ' + this.name + '.' );
};
Person.prototype.sayAge = function() {
if ( this.age ) {
console.log( 'I am ' + this.age + ' yrs old!' );
} else {
console.log( 'I do not know my age!' );
}
};
Person.prototype.age = 0.7;
//-----------
var person = new Person( 'Lucy' );
console.log( 'person.name', person.name ); // Lucy
console.log( 'person.age', person.age ); // 0.7
person.sayAge(); // I am 0.7 yrs old!
Посмотрите, как Люси age
условно объявлен и инициализирован.