2010-09-29 65 views
2

基本上所有关于JavaScript中成员枚举的人都主张使用hasOwnProperty方法来避免使用原型链。我关于JavaScript的原型继承和hasOwnProperty方法的困境

我知道这是防御性编程的一种形式,以防止对已添加的成员(例如Object.prototype)进行迭代。但其他遗传成员呢?比如说,原型链中非常接近的成员......实际上你想要枚举的成员。

比方说,我有以下几点:

var beget = function (o) { // http://javascript.crockford.com/prototypal.html 
    function F() {}; 
    F.prototype = o; 
    return new F(); 
}; 

var john = { name: 'john', surname: 'grech' }, 
    mary = beget(john), 
    p; 

mary.age = 42; //augmenting 'mary' 

// 'surname' in mary    => true 
// mary.hasOwnProperty('surname') => false 

for (p in mary) { 
    //skipping over non-direct members, meaning that we also skip members 
    //inherited from 'john' 
    if (!mary.hasOwnProperty(p)) { 
     continue; 
    } 
    console.log(p); 
} 

在上面的例子中,只有age会显示出来,因为agemary唯一的直接成员......其他两名成员,namesurname ,是原型链。

但显然,我希望所有3个成员迭代在for..in构造;但如果您删除hasOwnProperty,则可以从Object.Prototype获得成员,如果有人向其添加功能的话。


所以这是我的困境。

您是否将原型继承与hasOwnProperty方法结合使用,但会导致在枚举过程中链接太远的成员面临风险?

或者您是否使用其他形式的继承,将成员直接添加到对象而不是原型?

回答

3

嗯。你说的“原型链非常接近”,但实际上,它意味着什么非常接近?三个级别是“接近”还是“远”?

无论如何,你可以改变一下beget函​​数,并为每个对象实现自己的hasOwnProperty函数,这些函数只会经过原型链直到Object级别。这将解决您通过不使用hasOwnProperty获取添加到Object.prototype的成员的难题。附代码如下:

var beget = function (o) { // http://javascript.crockford.com/prototypal.html 
    function F() { 
     this.hasOwnProperty = function(key) { 
      return (key != "hasOwnProperty" 
       && Object.prototype.hasOwnProperty.call(this, key) 
       || o.hasOwnProperty(key) 
      ); 
     } 
    }; 

    F.prototype = o; 
    return new F(); 
}; 

var john = { name: 'john', surname: 'grech' }, 
    mary = beget(john), 
    p = beget(mary); 

mary.age = 42; //augmenting 'mary' 
mary.name = "mary"; 
p.size = "38"; 

// testing prototype of Object. 
Object.prototype.not_own = function(){} 

for(var i in p) { 
    console.debug('Key',i, p.hasOwnProperty(i)); 
} 

// p.hasOwnProperty("size"); // -> true 
// p.hasOwnProperty("age");  // -> true 
// p.hasOwnProperty("name"); // -> true 
// p.hasOwnProperty("not_own"); // -> false 
0

如果您需要遍历对象的原型链,则可以使用hasOwnProperty跳过直接成员(如您所说)。这当然也会通过添加到该对象原型的其他成员(Object.Prototype等)进行迭代。没有办法避免这种情况。

这就像要求如何避免枚举某个car = {yellow, green, black}对象的某些成员(伪代码)......您不......您只是根据它们的值跳过某些成员。


添加成员直接一个对象是不是真的继承的一种形式,当然,除非你创建一个使用begetObject()技术的对象......因为它使用了原型添加成员。

+0

我没有说通过增加直接成员来增加对象就是继承。但是,使用'beget'函数,您正在使用原型继承,因为您'继承'的类的成员被添加到原型。 – 2010-09-29 09:26:06

+0

就这样说,你的回答并没有让我更接近理解应该做什么。 – 2010-09-29 09:26:33

+0

@Andreas:你想要做什么并不是很清楚。如果你试图遍历一个对象,我回答了你的问题。如果你试图使用直接成员和begetObject()来进行继承,那么你的问题是什么? – 2010-09-29 09:33:03