为什么当我在这个JavaScript对象上使用反射时,我可以'看不到在其原型对象中定义的属性

Why when I use reflection on this JavaScript object I can't see a property defined in its prototype object?

本文关键字:对象 看不到 原型 属性 定义 我可以 JavaScript 为什么 反射      更新时间:2023-09-26

我对JavaScript很陌生,实际上我正在教程中学习反射概念。

所以我有以下代码:

/* REFLECTION AND EXTEND:
REFLECTION: An object can look at itself listing and changing its properties and methods. So it means that a JavaScript object have the ability to look at its own properties and methods. We can use this feature of the JavaScript language to implement a very userful pattern called EXTEND.
*/

/* This is a generic person object that have 'firstname' and 'lastname' peropertiest setted on a 'Default' value. This generic person object provide also a getFullName() method that return the concatenation of the firstname and the lastname
*/
var person = {
    firstname: 'Default',
    lastname: 'Default',
    getFullName: function() {
        return this.firstname + ' ' + this.lastname;  
    }
}
/* This john object represent a specific person but do not provide the getFullName() method: */
var john = {
    firstname: 'John',
    lastname: 'Doe'
}
// don't do this EVER! for demo purposes only !!! 
/* This set the 'person' object on the proto variable of the john object. So from this john object I can also use the getFullName() method defined for the generic person object: */
john.__proto__ = person;

// Now, we are going to see an example of the use of reflection in JavaScript:

for (var prop in john) {            // Iterate on all the properties into the john object (prop is the current property during the iteration)
    if (john.hasOwnProperty(prop)) {
        // propo is the current property name and john[prop] is the related value of this property into the john object:
        console.log(prop + ': ' + john[prop]);      
    }
}

代码非常简洁,注释解释了它的作用。

因此,我有一个通用的person对象,它提供了getFullName()方法,还有一个john的对象,它代表一个特定的人,但还没有定义getFullName(。

然后我做:

john.__proto__ = person;

也就是说person对象是john物体的原型,所以这意味着john物件继承自personohn对象可以访问getFullName()方法中的alsto。

然后,我使用反射来迭代john对象,并打印这些对象的所有属性。

我得到了这个结果:

firstname: John
lastname: Doe

这在我看来很奇怪,因为正如我在教程中所看到的,我希望也能看到这个属性:

getFullName: function() {
    return this.firstname + ' ' + this.lastname;  
}

因为现在我可以访问它。

为什么我看不见?我错过了什么?问题出在哪里?

正如大家所看到的,Juhana已经在评论中回答了这个问题,但我想补充我的解释。

当你这样做:

john.__proto__ = person;

我认为它连接两个对象,因为Object john具有person的原型。因此john可以访问person对象中的所有可用属性。

尽管如此,这并没有将person对象的属性添加到对象john,但它们之间按照__proto__有一个连接。因此,john仍然有自己的道具,并且可以访问person对象中的方法。

这种情况:

if (john.hasOwnProperty(prop)) {

不允许它记录其原型的属性。

hasOwnProperty限制对迭代中当前对象的属性访问。

首先要避免使用proto,因为它在所有浏览器中都不一样。现在proto向prototype添加东西,即进行继承。在使用john.hasOwnProperty(prop)时,只对自己的属性为true,而对继承的属性不为true,这就是为什么getFullName