如何检查是否在JavaScript类中定义了方法

时间:2011-04-10 15:21:18

标签: javascript

我需要检查一个类定义是否通过继承提供,一个特定的方法。我是否需要前往原型链来实现这一目标?

function TestClass(config){
    //NOTE: cannot instantiate class because if config not valid Error is thrown
}
TestClass.prototype.sampleMethod = function(){};

function isDefined(klass){
      console.log(typeof klass.sampleMethod); //'undefined'
      console.log('sampleMethod' in klass); //false
      console.log(klass['sampleMethod']); //undefined

      console.log(typeof klass.prototype.sampleMethod); //'function' ...inheritance?
}

isDefined(TestClass);

4 个答案:

答案 0 :(得分:1)

我认为问题可能是你不能检测一个类是否直接实现了什么而不查看类的实例,除非你专门将它的实例分配给新类的原型进行检查。请记住,当为类的原型提供属性sampleMethod时,它是一个表示原型的实例对象,而不是类。实际上,类在JavaScript中并不像那样存在。

function TestClass(config){}
TestClass.prototype.sampleMethod = function(){};

function isDefined(klass){
  var holder, _defined = false;
  try{
    holder = new klass({});
    _defined = typeof holder.sampleMethod !== 'undefined'; // does the prototype lookup for you
  }catch(e){
    console.log('Error loading class for reasons other than invalid method.', e)
  }finally{
    return _defined;
  }
}

答案 1 :(得分:0)

这是你想要的吗?

function TestClass(config) {}
TestClass.prototype.sampleMethod = function() {};

function isDefined(klass, method) {
    return (klass && method ?
    function() {
        return !!klass.prototype[method];
    }() : false);
}

这样做的示例:http://fiddle.jshell.net/Shaz/2kL9A/

答案 2 :(得分:0)

是的,您需要检查原型链。

function TestClass(config){}
TestClass.prototype.sampleMethod = function(){};

function TestClass2() {}
TestClass2.prototype = TestClass;

function isDefined(obj, method) {
    if (obj.prototype !== undefined) {
        var methodInPrototype = (method in obj.prototype);
        console.log("Is " + method + " in prototype of " + obj + ": " + methodInPrototype);
        if (methodInPrototype) {
                return true;
        } else {
            isDefined(obj.prototype, method);
        }
    }
    return false;
}

isDefined(TestClass, "sampleMethod");
isDefined(TestClass2, "sampleMethod");
isDefined(TestClass2, "sampleMethod2");

打印:

// Is sampleMethod in prototype of function TestClass(config) {}: true
// Is sampleMethod in prototype of function TestClass2() {}: false
// Is sampleMethod in prototype of function TestClass(config) {}: true
// Is sampleMethod2 in prototype of function TestClass2() {}: false
// Is sampleMethod2 in prototype of function TestClass(config) {}: false

答案 3 :(得分:0)

我不明白你为什么要测试一个构造函数,我只是直接测试一个对象,看它是否有一个特定的方法。

无论如何,加布里埃尔非常接近,但我的做法有点不同:

function MyConstructor(){}
MyConstructor.prototype.sampleMethod = function(){};

// Return true if instances of constructor have method
// Return false if they don't
// Return undefined if new constructor() fails 
function isDefined(constructor, method){
  var temp, defined;
  try {
    temp = new constructor();
    defined = !!(typeof temp[method] == 'function');
  } catch(e) {
    // calling - new constructor - failed
  }
  return defined;
}

var foo;

alert(
  isDefined(MyConstructor, 'sampleMethod')             // Method on MyConstructor.prototype
  + '\n' + isDefined(MyConstructor, 'undefinedMethod') // Not defined
  + '\n' + isDefined(MyConstructor, 'toString')        // Method on Object.prototype
  + '\n' + isDefined(foo, 'foo')                       // foo is not a constructor
);

当然上面只适用于[[prototype]]的经典原型继承,在使用模块模式或类似模式时需要其他东西(即使用闭包的“inhertiance”)。