测试某些东西是否是javascript中的类

kgr*_*rad 18 javascript

嘿所有,我试图测试传递给我的函数的参数是否是类名,以便我可以使用instanceof将其与其他类进行比较.

例如:

function foo(class1, class2) {
  // Test to see if the parameter is a class.
  if(class1 is a class)
  {
    //do some kind of class comparison.
    if(class2 is a class)
    {
       if(class1 instanceof class2)
       {
          //...
       }
    }
    else
    {
       //...
    }
  }
  else
    //...
}
Run Code Online (Sandbox Code Playgroud)

这可能吗?我在google答案时遇到了麻烦.

the*_*art 17

在javascript中确实没有"类"这样的东西 - 除了原语之外的一切都是对象.甚至函数都是对象.

instanceof DOES可以使用函数.看看这个链接.

function Car(make, model, year)
{
  this.make = make;
  this.model = model;
  this.year = year;
}
var mycar = new Car("Honda", "Accord", 1998);
var a = mycar instanceof Car;    // returns true
var b = mycar instanceof Object; // returns true
Run Code Online (Sandbox Code Playgroud)

  • “一切都是对象” - 不完全是。原始类型(数字、字符串、布尔、空和未定义)不是对象。 (3认同)
  • @AndreasGrech - 不完全是,甚至原始类型都有属性和方法以及原型链等...所以它们也是某种对象 (2认同)

Nat*_*ate 14

这是一种快速而肮脏的方法来确定您是否有一个类或一个函数。

function myFunc() { };
class MyClass() { };

Object.getOwnPropertyNames(myFunc);
// -> [ 'length', 'name', 'arguments', 'caller', 'prototype' ]

Object.getOwnPropertyNames(MyClass);
// -> [ 'length', 'prototype', 'name' ]
Run Code Online (Sandbox Code Playgroud)

所以我们知道我们有一个函数而不是一个类 ifarguments是一个属性名称:

Object.getOwnPropertyNames(myFunc).includes('arguments');
// -> true

Object.getOwnPropertyNames(MyClass).includes('arguments');
// -> false
Run Code Online (Sandbox Code Playgroud)

箭头函数和aysnc函数不会有arguments属性名称或prototype. 更完整的示例可能如下所示(假设我们知道输入只能是函数或类):

function isFunction(funcOrClass) {
  const propertyNames = Object.getOwnPropertyNames(funcOrClass);
  return (!propertyNames.includes('prototype') || propertyNames.includes('arguments'));
}
Run Code Online (Sandbox Code Playgroud)

function myFunc() { };
class MyClass() { };

Object.getOwnPropertyNames(myFunc);
// -> [ 'length', 'name', 'arguments', 'caller', 'prototype' ]

Object.getOwnPropertyNames(MyClass);
// -> [ 'length', 'prototype', 'name' ]
Run Code Online (Sandbox Code Playgroud)

  • 至少在node.js环境中:Object.getOwnPropertyNames(() => 123).includes('arguments'); // === 假 (2认同)
  • @PanuLogic 你使用的箭头函数也没有 `prototype`,所以如果你知道你得到的是一个类或一个函数,你也可以检查 `prototype`。我会更新我的答案。请注意,`Object.getOwnPropertyNames(function () { 123 }).includes('arguments');` 在 Node 中按预期工作。 (2认同)
  • 不幸的是,如果该函数是在设置了“use strict”的脚本上声明的,则它可能不起作用。 (2认同)

aik*_*eru 7

既然我们有ES6的原生实现,那么就有"真正的类".与构造函数一样,这些主要用于原型继承的语法糖,但存在细微差别,两者不完全可互换.

到目前为止,我已经找到了唯一的办法就是让.toString()对象原型的构造函数,并检查它是否与启动class,或者如果对象有一个构造函数和.toString()那个开头class.

请注意,如果您的代码已编译(即:大多数Babel或TypeScript设置),那么这将返回function...而不是class...在运行时(因为类被转换为构造函数).

function isClass(obj) {
  const isCtorClass = obj.constructor
      && obj.constructor.toString().substring(0, 5) === 'class'
  if(obj.prototype === undefined) {
    return isCtorClass
  }
  const isPrototypeCtorClass = obj.prototype.constructor 
    && obj.prototype.constructor.toString
    && obj.prototype.constructor.toString().substring(0, 5) === 'class'
  return isCtorClass || isPrototypeCtorClass
}
Run Code Online (Sandbox Code Playgroud)

这仅适用于已class针对尚未转换为的代码实施的本机环境(Chrome,Firefox,Edge,node.js等)function.

用法:

class A {}
class B extends A {}
isClass(A) // true
isClass(new A()) // true
isClass(B) // true
isClass(new B()) // true

function C() {}
isClass(C) // false
isClass(new C()) // false
isClass({}) // false
isClass(Date) // false
isClass(new Date()) // false

//These cases return 'true' but I'm not sure it's desired
isClass(Object.create(A)) // true    
const x = {}
Object.setPrototypeOf(x, A)
isClass(x) // true
Run Code Online (Sandbox Code Playgroud)

如果有更好的方法,我很想知道它是什么.

  • 在我看来, isClass(new A()) 应该返回 false。A 是一个类,但是 new A() 是一个类的实例,而不是一个类。 (6认同)