如何获取JavaScript对象的类?

2020/09/21 10:31 · javascript ·  · 0评论

我创建了一个JavaScript对象,但是如何确定该对象的类呢?

我想要类似Java的.getClass()方法。

getClass()JavaScript中没有Java的完全对应版本通常,这是由于JavaScript是基于原型的语言,而不是Java是基于类的语言

根据您的需要getClass(),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参数,您可以使用gulpgrunt设置为false

obj.constructor.name

是现代浏览器中的可靠方法。Function.name已在ES6中正式添加到该标准中,从而使这成为将JavaScript对象的“类”作为字符串获取的符合标准的方法。如果使用实例化该对象var obj = new MyClass(),它将返回“ MyClass”。

它将为数字返回“ Number”,为数组返回“ Array”,为函数返回“ Function”,等等。它的行为通常与预期的一样。失败的唯一情况是通过原型创建的对象没有原型Object.create( null ),或者该对象是从匿名定义(未命名)的函数实例化的。

另请注意,如果要压缩代码,则与硬编码类型字符串进行比较是不安全的。例如,而不是检查是否obj.constructor.name == "MyType",而是检查obj.constructor.name == MyType.name或者只是比较构造函数本身,但是这将无法跨DOM边界,因为每个DOM上都有不同的构造函数实例,因此无法在其构造函数上进行对象比较。

此getNativeClass()函数返回"undefined"未定义的值和"null"null。
对于所有其他值,CLASSNAME-part是从中提取的[object CLASSNAME],这是使用的结果Object.prototype.toString.call(value)

getAnyClass() 的行为与getNativeClass()相同,但也支持自定义构造函数

function getNativeClass(obj) {
  if (typeof obj === "undefined") return "undefined";
  if (obj === null) return "null";
  return Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
}

function getAnyClass(obj) {
  if (typeof obj === "undefined") return "undefined";
  if (obj === null) return "null";
  return obj.constructor.name;
}

getClass("")   === "String";
getClass(true) === "Boolean";
getClass(0)    === "Number";
getClass([])   === "Array";
getClass({})   === "Object";
getClass(null) === "null";

getAnyClass(new (function Foo(){})) === "Foo";
getAnyClass(new class Foo{}) === "Foo";

// etc...

要获取“伪类”,您可以通过以下方式获取构造函数:

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)上使用。

您可以使用构造函数属性获取对创建对象的构造函数的引用

function MyObject(){
}

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

如果需要在运行时确认对象的类型,则可以使用instanceof运算符:

obj instanceof MyObject // true

为了保持其向后兼容的不间断记录ECMAScript 6,JavaScript仍然没有class类型(尽管不是每个人都理解这一点)。确实创建原型的语法包含一个class关键字,class仍然没有一个叫做class的东西JavaScript现在不是,并且从来都不是经典的OOP语言从类的角度讲JS只是一种误导,或者是尚未取消原型继承的迹象(只是保持它的真实性)。

这意味着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年,classJavaScript中有一个关键字,但仍然没有类类型。this.constructor是获取构造函数this.constructor.prototype的最佳方法也是访问原型本身的最佳方法。

我有一种情况现在可以通用工作,并使用了:

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" 

对于ES6中的Javascript类,可以使用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... );

在javascript中,没有任何类,但我认为您需要构造函数名称,并obj.constructor.toString()会告诉您所需的内容。

我发现在IE中object.constructor.toString()返回[object objectClass],而不是function objectClass () {}在选择中返回。因此,我认为http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects中的代码在IE中可能无法正常工作。我将代码修复如下:

码:

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; 
    };
    

同意dfa,这就是为什么在找不到命名类的情况下我将原型视为类的原因

这是Eli Grey发布的功能的升级功能,以符合我的想法

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;
}

如果您不仅需要GET类,还需要仅通过一个实例来扩展它,请编写:

让我们

 class A{ 
   constructor(name){ 
     this.name = name
   }
 };

 const a1 = new A('hello a1');

因此扩展具有实例的A仅使用:

const a2 = new (Object.getPrototypeOf(a)).constructor('hello a2')
// the analog of const a2 = new A()

console.log(a2.name)//'hello a2'

我建议使用Object.prototype.constructor.name

Object.defineProperty(Object.prototype, "getClass", {
    value: function() {
      return this.constructor.name;
    }
});

var x = new DOMParser();
console.log(x.getClass()); // `DOMParser'

var y = new Error("");
console.log(y.getClass()); // `Error'

这是getClass()的实现getInstance()

您可以使用来获取对象类的引用this.constructor

从实例上下文中:

function A() {
  this.getClass = function() {
    return this.constructor;
  }

  this.getNewInstance = function() {
    return new this.constructor;
  }
}

var a = new A();
console.log(a.getClass());  //  function A { // etc... }

// you can even:
var b = new (a.getClass());
console.log(b instanceof A); // true
var c = a.getNewInstance();
console.log(c instanceof A); // true

从静态上下文:

function A() {};

A.getClass = function() {
  return this;
}

A.getInstance() {
  return new this;
}

您也可以这样做

 class Hello {
     constructor(){
     }
    }
    
      function isClass (func) {
        return typeof func === 'function' && /^class\s/.test(Function.prototype.toString.call(func))
    }
    
   console.log(isClass(Hello))

这将告诉您输入是否为类

还有另一种识别您的类的技术。您可以在下面的实例中将ref存储到您的类中。

class MyClass {
    static myStaticProperty = 'default';
    constructor() {
        this.__class__ = new.target;
        this.showStaticProperty = function() {
            console.log(this.__class__.myStaticProperty);
        }
    }
}

class MyChildClass extends MyClass {
    static myStaticProperty = 'custom';
}

let myClass = new MyClass();
let child = new MyChildClass();

myClass.showStaticProperty(); // default
child.showStaticProperty(); // custom

myClass.__class__ === MyClass; // true
child.__class__ === MyClass; // false
child.__class__ === MyChildClass; // true

Javascript是一种无类语言:没有类可以像Java中一样静态地定义类的行为。JavaScript使用原型而不是类来定义对象属性,包括方法和继承。使用JavaScript中的原型可以模拟许多基于类的功能。

问题似乎已经回答了,但OP希望访问和对象的类,就像我们在Java中所做的那样,所选答案还不够(恕我直言)。

通过以下解释,我们可以获得对象的类(实际上在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原型实例化的所有对象,我们必须定义.lastArray原型属性:

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'是数组的情况下,我们可以arr通过使用' arr.__proto__' 引用' ' 的类来添加新属性

我们访问了'的原型,arr却不知道它是Array的一个实例,我认为这就是OP的要求。

本文地址:http://javascript.askforanswer.com/ruhehuoqujavascriptduixiangdelei.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!