如何确保函数/方法参数是certian类型?

时间:2016-05-08 12:34:04

标签: javascript

是否可以确保函数/方法参数具有某种类型?

例如,我有一个简单的Character类,它接受一个可选的Health对象。是否可以检查该参数是否为Health类型?当应用程序需要Health对象时,我不希望使用者传入整数。

let Character = function(health) {
    if(typeof health === 'undefined')
        this.health = new Health(100);
    else
        this.health = health;
};

Character.prototype.hit = function(hitPoints) {
    this.health.subtract(hitPoints);
};

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

在这种特殊情况下,是的,您有两种选择:

  1. instanceof

    if (health instanceof Health) {
        // It's a Health object *OR* a derivative of one
    }
    

    从技术上讲,instanceof检查的对象是Health.prototype引用的对象是health的原型链。

  2. 检查constructor

    if (health.constructor === Health) {
        // Its `constructor` is `Health`, which usually (but not necessarily)
        // means it was constructed via Health
    }
    

    请注意,这很容易伪造:let a = {}; a.constructor = Health;

  3. 通常你可能想要达到前者,因为A)它允许Health的子类型,和B)当使用ES5和更早的语法进行继承层次结构时,很多人们忘记修复constructor并最终指向错误的功能。

    ES5语法中的示例:

    var Health = function() {
    };
    
    var PhysicalHealth = function() {
      Health.call(this);
    };
    PhysicalHealth.prototype = Object.create(Health.prototype);
    PhysicalHealth.prototype.constructor = PhysicalHealth;
    
    var h = new PhysicalHealth();
    log(h instanceof Health);     // true
    log(h.constructor == Health); // false
    
    function log(msg) {
      var p = document.createElement('p');
      p.appendChild(document.createTextNode(msg));
      document.body.appendChild(p);
    }

    或使用ES2015(ES6):

    class Health {
    }
    
    class PhysicalHealth extends Health {
    }
    
    let h = new PhysicalHealth();
    log(h instanceof Health);     // true
    log(h.constructor == Health); // false
    
    function log(msg) {
      let p = document.createElement('p');
      p.appendChild(document.createTextNode(msg));
      document.body.appendChild(p);
    }

答案 1 :(得分:0)

简短的做法...

let character = function(health) { this.health = (health instanceof Health) ? health : new Health(100); }