NullPointerException
s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException
. Они наиболее распространены, но другие способы перечислены на странице NullPointerException
javadoc.
Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException
, be:
public class Example {
public static void main(String[] args) {
Object obj = null;
obj.hashCode();
}
}
В первой строке внутри main
я явно устанавливаю ссылку Object
obj
равной null
. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException
, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.
(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)
В JavaScript нет точного аналога Java getClass()
. В основном это связано с тем, что JavaScript является языком на основе прототипа , в отличие от Java, являющегося на основе класса .
В зависимости от того, что вам нужно getClass()
for, в JavaScript есть несколько вариантов:
typeof
instanceof
obj.
constructor
func.
prototype
, proto
. isPrototypeOf
Несколько примеров:
function Foo() {}
var foo = new Foo();
typeof Foo; // == "function"
typeof foo; // == "object"
foo instanceof Foo; // == true
foo.constructor.name; // == "Foo"
Foo.name // == "Foo"
Foo.prototype.isPrototypeOf(foo); // == true
Foo.prototype.bar = function (x) {return x+x;};
foo.bar(21); // == 42
Примечание: если вы компилируете свой код с помощью Uglify, это изменит имена неглобальных классов. Чтобы предотвратить это, Uglify имеет параметр --mangle
, который вы можете установить на false, использует gulp или grunt .
Согласитесь с dfa, поэтому я рассматриваю прототип как класс, когда ни один из названных классов не найден
. Ниже приведена обновленная функция той, которую опубликовал Эли Грей, чтобы соответствовать моему образу ума
function what(obj){
if(typeof(obj)==="undefined")return "undefined";
if(obj===null)return "Null";
var res = Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
if(res==="Object"){
res = obj.constructor.name;
if(typeof(res)!='string' || res.length==0){
if(obj instanceof jQuery)return "jQuery";// jQuery build stranges Objects
if(obj instanceof Array)return "Array";// Array prototype is very sneaky
return "Object";
}
}
return res;
}
getClass()
и getInstance()
. Вы можете получить ссылку для класса Object с помощью window
.
function A() {
this.getClass = function() {
return window[this.constructor.name];
}
this.getNewInstance = function() {
return new window[this.constructor.name];
}
}
var a = new A();
console.log(a.getClass()); // function A { // etc... }
// you can even:
var b = new a.getClass();
b instanceof A; // true
function B() {};
B.getClass = function() {
return window[this.name];
}
B.getInstance() {
return new window[this.name];
}
Вы можете получить ссылку на конструкторскую функцию, которая создала объект, используя свойство конструктора :
function MyObject(){
}
var obj = new MyObject();
obj.constructor; // MyObject
Если вам нужно подтвердить тип объекта в вы можете использовать оператор instanceof :
obj instanceof MyObject // true
obj.constructor.name
работает в большинстве случаев в современных браузерах, несмотря на то, что Function.name
официально не добавлен в стандарт до ES6. Если объект создается с помощью var obj = new MyClass()
, он вернет «MyClass» в виде строки.
Он вернет «Номер» для чисел, «Массив» для массивов и «Функция» для функций и т. Д. Это кажется вполне надежным. Единственными случаями, когда он терпит неудачу, является то, что объект создается без прототипа через Object.create( null )
или объект был создан из анонимно определенной (неназванной) функции.
Возможно, obj.constructor.name
более интуитивно понятный, чем typeof
, и может быть инкапсулирован в функцию для обработки нечетного случая, когда constructor
не определен (и для обработки нулевых ссылок).
Примечание. Еще одно преимущество этого метода он работает интуитивно через границы DOM по сравнению с непосредственным сравнением объектов-конструкторов или с использованием instanceOf
. Причина, по которой вы не можете рассчитывать, - это фактически разные экземпляры функции конструктора для каждой DOM, поэтому сравнение объектов с их конструкторами не будет работать.
Примечание 2: Как ни странно , этот метод, как представляется, возвращает имя самой основной функции, используемой в цепочке прототипов, что, к сожалению, не является интуитивным. Например, если B
происходит прототипом с A
, и вы создаете новый экземпляр B
, b
, b.constructor.name
возвращает «A»! Так что он чувствует себя полностью назад. Однако он отлично работает для одноуровневых прототипов и всех примитивов.
Function.name
еще не является частью стандарта JavaScript. В настоящее время он поддерживается в Chrome и Firefox, но не в IE (10).
– Halcyon
4 November 2013 в 18:44
Object.create(something).constructor === something.constructor
, что также неверно. Таким образом, obj.constructor ненадежен для всех объектов, созданных с Object.create, независимо от прототипа или без него.
– user2451227
22 July 2014 в 11:55
obj.constructor.name
работает только для с именем i>. I.e., если я определяю var Foo = function() {}
, то для var foo = new Foo()
, foo.constructor.name
даст вам пустую строку.
– KFL
1 September 2014 в 09:02
constructor.name
, если ваш код будет уменьшен. Имя функции будет меняться произвольно.
– igorsantos07
31 March 2016 в 21:29
Javascript - это классы без классов: нет классов, которые определяют поведение класса статически, как в Java. JavaScript использует прототипы вместо классов для определения свойств объекта, включая методы и наследование. Можно моделировать многие функции на основе классов с прототипами в JavaScript.
class
. Он имеет ключевое слово class
и class
для создания прототипов, в которых методы могут более легко получить доступ super
.
– james_womack
1 August 2016 в 03:08
Эта функция возвращает либо "undefined"
, "null"
, либо "class"
в [object class]
из Object.prototype.toString.call(someObject)
.
function getClass(obj) {
if (typeof obj === "undefined")
return "undefined";
if (obj === null)
return "null";
return Object.prototype.toString.call(obj)
.match(/^\[object\s(.*)\]$/)[1];
}
getClass("") === "String";
getClass(true) === "Boolean";
getClass(0) === "Number";
getClass([]) === "Array";
getClass({}) === "Object";
getClass(null) === "null";
// etc...
"Object"
.
– Halcyon
4 November 2013 в 18:46
Для классов Javascript в ES6 вы можете использовать object.constructor
. В классе примеров ниже метод getClass()
возвращает класс ES6, как и следовало ожидать:
var Cat = class {
meow() {
console.log("meow!");
}
getClass() {
return this.constructor;
}
}
var fluffy = new Cat();
...
var AlsoCat = fluffy.getClass();
var ruffles = new AlsoCat();
ruffles.meow(); // "meow!"
Если вы создаете экземпляр класса из метода getClass
, обязательно заверните его в скобки, например. ruffles = new ( fluffy.getClass() )( args... );
В соответствии с его непрерывной записью обратной совместимости, ECMAScript 6, JavaScript по-прежнему не имеет типа class
(хотя не все это понимают). У этого есть ключевое слово class
как часть его синтаксиса class
для создания прототипов, но все еще не называется классом. JavaScript теперь не является и никогда не был классическим языком ООП. Говоря о JS в терминах класса, это либо вводит в заблуждение, либо признак еще не grokking прототипа наследования (просто сохраняя его реальным).
Это означает, что this.constructor
все еще отличный способ получить ссылку на constructor
. И this.constructor.prototype
- это способ доступа к самому прототипу. Поскольку это не Java, это не класс. Это объект-прототип, из которого был создан ваш экземпляр. Вот пример использования синтаксического сахара ES6 для создания цепочки прототипов:
class Foo {
get foo () {
console.info(this.constructor, this.constructor.name)
return 'foo'
}
}
class Bar extends Foo {
get foo () {
console.info('[THIS]', this.constructor, this.constructor.name, Object.getOwnPropertyNames(this.constructor.prototype))
console.info('[SUPER]', super.constructor, super.constructor.name, Object.getOwnPropertyNames(super.constructor.prototype))
return `${super.foo} + bar`
}
}
const bar = new Bar()
console.dir(bar.foo)
Это то, что выводится с помощью babel-node
:
> $ babel-node ./foo.js ⬡ 6.2.0 [±master ●]
[THIS] [Function: Bar] 'Bar' [ 'constructor', 'foo' ]
[SUPER] [Function: Foo] 'Foo' [ 'constructor', 'foo' ]
[Function: Bar] 'Bar'
'foo + bar'
Там у вас есть! В 2016 году в JavaScript есть ключевое слово class
, но до сих пор не существует типа класса. this.constructor
- лучший способ получить конструкторскую функцию, this.constructor.prototype
лучший способ получить доступ к самому прототипу.
В javascript нет классов, но я думаю, что вы хотите, чтобы имя конструктора и obj.constructor.toString()
рассказывали вам, что вам нужно.
.name
.
– devios1
3 January 2012 в 18:39
У меня была ситуация, когда теперь работала родовая и использовала это:
class Test {
// your class definition
}
nameByType = function(type){
return type.prototype["constructor"]["name"];
};
console.log(nameByType(Test));
это единственный способ, которым я нашел, чтобы получить имя класса по типу ввода, если у вас нет экземпляра объекта .
(записано в ES2017)
Точечная запись также отлично работает
console.log(Test.prototype.constructor.name); // returns "Test"
Вопрос кажется уже отвеченным, но OP хочет получить доступ к классу и объекту, точно так же, как мы делаем на Java, и выбранного ответа недостаточно (imho).
Со следующим объяснением мы можем получить класс объекта (он на самом деле называется прототипом в javascript).
var arr = new Array('red', 'green', 'blue');
var arr2 = new Array('white', 'black', 'orange');
Вы можете добавить свойство, подобное этому:
Object.defineProperty(arr,'last', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
Но свойство .last
будет только быть доступным для объекта [arr
», который создается экземпляром прототипа Array. Таким образом, чтобы свойство .last
было доступно для всех объектов, созданных из прототипа Array, мы должны определить свойство .last
для прототипа Array:
Object.defineProperty(Array.prototype,'last', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
console.log(arr2.last) // orange
Проблема здесь заключается в том, вы должны знать, какой тип объекта (прототип) принадлежит переменным 'arr
' и 'arr2
'! Другими словами, если вы не знаете тип класса (прототип) объекта 'arr
', то вы не сможете определить для них свойство. В приведенном выше примере мы знаем, что arr является экземпляром объекта Array, поэтому мы использовали Array.prototype для определения свойства для Array. Но что, если мы не знали класс (прототип) «arr
»?
Object.defineProperty(arr.__proto__,'last2', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
console.log(arr2.last) // orange
Как вы можете видеть, не зная, что 'arr
' является массивом, мы можем добавьте новое свойство, просто bu ссылающееся на класс 'arr
', используя 'arr.__proto__
'.
Мы обратились к прототипу «arr
», не зная, что это экземпляр массива и я думаю, что это то, о чем спросил ОП.
Я нахожу object.constructor.toString()
return [object objectClass]
в IE, а не function objectClass () {}
возвращен в chome. Итак, я думаю, что код в http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects может не работать хорошо в IE.And I исправил код следующим образом:
var getObjectClass = function (obj) {
if (obj && obj.constructor && obj.constructor.toString()) {
/*
* for browsers which have name property in the constructor
* of the object,such as chrome
*/
if(obj.constructor.name) {
return obj.constructor.name;
}
var str = obj.constructor.toString();
/*
* executed if the return of object.constructor.toString() is
* "[object objectClass]"
*/
if(str.charAt(0) == '[')
{
var arr = str.match(/\[\w+\s*(\w+)\]/);
} else {
/*
* executed if the return of object.constructor.toString() is
* "function objectClass () {}"
* for IE Firefox
*/
var arr = str.match(/function\s*(\w+)/);
}
if (arr && arr.length == 2) {
return arr[1];
}
}
return undefined;
};
Чтобы получить «псевдокласс», вы можете получить функцию-конструктор, [// g1]
obj.constructor
, предполагая, что constructor
правильно задан, когда вы выполняете наследование - что-то вроде:
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
, и эти две строки вместе с:
var woofie = new Dog()
сделают woofie.constructor
точкой Dog
. Обратите внимание, что Dog
является конструкторской функцией и является объектом Function
. Но вы можете сделать if (woofie.constructor === Dog) { ... }
.
Если вы хотите получить имя класса в виде строки, я нашел следующее хорошо работает:
http: // blog. magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects
function getObjectClass(obj) {
if (obj && obj.constructor && obj.constructor.toString) {
var arr = obj.constructor.toString().match(
/function\s*(\w+)/);
if (arr && arr.length == 2) {
return arr[1];
}
}
return undefined;
}
Он получает функцию-конструктор, преобразует ее в строку и извлекает имя функции конструктора.
Обратите внимание, что obj.constructor.name
мог бы работать хорошо, но он не является стандартным. Это на Chrome и Firefox, но не на IE, включая IE 9 или IE 10 RTM.
func.prototype
(да, функции - это объекты, но свойствоprototype
применимо только к объектам функций). – Miles 8 August 2009 в 19:37instanceof
/isPrototypeOf()
и нестандартный__proto__
– Christoph 8 August 2009 в 19:46Object.getPrototypeOf()
– Christoph 8 August 2009 в 19:52Foo
довольно печатная. В комментариях не указаны возвращаемые значения, а равенства, которые сохраняются для возвращаемых значений. Таким образом, комментарий означает, чтоfoo.constructor == Foo
выполняется, что также будет иметь место для вас. – earl 24 October 2010 в 22:12constructor.name
, если ваш код будет уменьшен. Имя функции будет меняться произвольно. – igorsantos07 31 March 2016 в 21:26