есть ли эквивалент Object.class в javascript? [Дубликат]

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, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

495
задан Boann 27 December 2014 в 14:04
поделиться

14 ответов

В JavaScript нет точного аналога Java getClass() . В основном это связано с тем, что JavaScript является языком на основе прототипа , в отличие от Java, являющегося на основе класса .

В зависимости от того, что вам нужно getClass() for, в JavaScript есть несколько вариантов:

Несколько примеров:

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 .

710
ответ дан James L. 20 August 2018 в 11:07
поделиться
  • 1
    Вероятно, это должно быть func.prototype (да, функции - это объекты, но свойство prototype применимо только к объектам функций). – Miles 8 August 2009 в 19:37
  • 2
    вы можете также упомянуть instanceof / isPrototypeOf() и нестандартный __proto__ – Christoph 8 August 2009 в 19:46
  • 3
    ES5 имеет Object.getPrototypeOf() – Christoph 8 August 2009 в 19:52
  • 4
    Да, clarkf, это Foo довольно печатная. В комментариях не указаны возвращаемые значения, а равенства, которые сохраняются для возвращаемых значений. Таким образом, комментарий означает, что foo.constructor == Foo выполняется, что также будет иметь место для вас. – earl 24 October 2010 в 22:12
  • 5
    Предупреждение : не полагайтесь на constructor.name, если ваш код будет уменьшен. Имя функции будет меняться произвольно. – igorsantos07 31 March 2016 в 21:26

Согласитесь с 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;
}
1
ответ дан Antkhan 20 August 2018 в 11:07
поделиться

Вот реализация 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];
}
-1
ответ дан Bruno Finger 20 August 2018 в 11:07
поделиться
  • 1
    Почему не только this.constructor? – Solomon Ucko 22 April 2016 в 16:42
  • 2
    Я не знаю, но если это будет лучше, вы можете определенно отредактировать ответ, чтобы улучшить его, когда найдете лучше, ведь это сообщество. – Bruno Finger 5 March 2018 в 11:38

Вы можете получить ссылку на конструкторскую функцию, которая создала объект, используя свойство конструктора :

function MyObject(){
}

var obj = new MyObject();
obj.constructor; // MyObject

Если вам нужно подтвердить тип объекта в вы можете использовать оператор instanceof :

obj instanceof MyObject // true
7
ответ дан CMS 20 August 2018 в 11:07
поделиться
  • 1
    не возвращает ли она сама конструкторская функция, например, вы можете вызвать ее снова и создать новый объект этого типа? – SparK 24 January 2012 в 19:19
  • 2
    @SparK Да, хотя вы все равно можете использовать это для сравнения, пока вы находитесь на одной и той же DOM (вы сравниваете объекты функции). Однако гораздо лучше перевести конструктор в строку и сравнить его, особенно потому, что он работает через границы DOM при использовании iframes. – devios1 15 February 2012 в 18:00
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»! Так что он чувствует себя полностью назад. Однако он отлично работает для одноуровневых прототипов и всех примитивов.

202
ответ дан devios1 20 August 2018 в 11:07
поделиться
  • 1
    Function.name еще не является частью стандарта JavaScript. В настоящее время он поддерживается в Chrome и Firefox, но не в IE (10). – Halcyon 4 November 2013 в 18:44
  • 2
    Object.create(something).constructor === something.constructor, что также неверно. Таким образом, obj.constructor ненадежен для всех объектов, созданных с Object.create, независимо от прототипа или без него. – user2451227 22 July 2014 в 11:55
  • 3
    obj.constructor.name работает только для с именем . I.e., если я определяю var Foo = function() {}, то для var foo = new Foo(), foo.constructor.name даст вам пустую строку. – KFL 1 September 2014 в 09:02
  • 4
    Предупреждение : не полагайтесь на constructor.name, если ваш код будет уменьшен. Имя функции будет меняться произвольно. – igorsantos07 31 March 2016 в 21:29
  • 5
    Имя функции является частью ES6, см. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – Janus Troelsen 20 June 2016 в 15:02

Javascript - это классы без классов: нет классов, которые определяют поведение класса статически, как в Java. JavaScript использует прототипы вместо классов для определения свойств объекта, включая методы и наследование. Можно моделировать многие функции на основе классов с прототипами в JavaScript.

0
ответ дан dfa 20 August 2018 в 11:07
поделиться
  • 1
    Я часто говорил, что Javascript не хватает класса :) – Steven 8 August 2009 в 19:51
  • 2
    Обновление: с ECMAScript 6 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...
22
ответ дан Eli Grey 20 August 2018 в 11:07
поделиться
  • 1
    Object.prototype.getClass = function () {использование 'this' вместо obj было бы неплохо – SparK 24 January 2012 в 19:20
  • 2
    конечно, то null и undefined были бы неконтролируемыми, поскольку только Object имел бы метод getClass – SparK 24 January 2012 в 19:25
  • 3
    Это работает только на собственных объектах. Если у вас есть какое-то наследство, вы всегда будете получать "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... );

3
ответ дан Hugheth 20 August 2018 в 11:07
поделиться

В соответствии с его непрерывной записью обратной совместимости, 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 лучший способ получить доступ к самому прототипу.

1
ответ дан james_womack 20 August 2018 в 11:07
поделиться

В javascript нет классов, но я думаю, что вы хотите, чтобы имя конструктора и obj.constructor.toString() рассказывали вам, что вам нужно.

2
ответ дан lucian.pantelimon 20 August 2018 в 11:07
поделиться
  • 1
    Это вернет полное определение функции конструктора в виде строки. Вы действительно хотите .name. – devios1 3 January 2012 в 18:39
  • 2
    но .name не определен даже в IE 9 – 太極者無極而生 4 October 2012 в 15:47

У меня была ситуация, когда теперь работала родовая и использовала это:

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" 
4
ответ дан mtizziani 20 August 2018 в 11:07
поделиться
  • 1
    Ах, вот что я искал. Если он не создан, вам нужно использовать «прототип», чтобы получить имя класса. Благодаря тонну! – Artokun 6 July 2018 в 03:47

Вопрос кажется уже отвеченным, но 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», не зная, что это экземпляр массива и я думаю, что это то, о чем спросил ОП.

-2
ответ дан Ramazan Polat 20 August 2018 в 11:07
поделиться

Я нахожу 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; 
    };
3
ответ дан zzy7186 20 August 2018 в 11:07
поделиться

Чтобы получить «псевдокласс», вы можете получить функцию-конструктор, [// 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.

17
ответ дан 太極者無極而生 20 August 2018 в 11:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: