首页 > 解决方案 > JS ES6 类语法和原型混淆

问题描述

好的,据我所知,我们会像这样编写一个类构造函数

class User {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    //anything outside of constructor belong to this.prototype

    getName() {
        console.log(this.name);
    }
    getAge() {
        console.log(this.age);
    }
}

所以相反,如果我写这样的东西:

class User {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    getName() {
        console.log(this.name);
    }
}

User.prototype.getAge = function () {
    console.log(this.age);
};

从技术上讲,它应该完全相同,对吧?还是我错了?因为当我尝试这其中的每一个时,我得到了 2 个不同的结果:

let user = new User('john', 23);

let properties = [];

for (let prop in user) {
    properties.push(prop);
}

console.log(properties); //The first code result : ["name", "age"]
                         //The second code result : ["name", "age", "getAge"]

那么两者有什么区别呢?

标签: javascriptprototype

解决方案


两者的区别在于 usingUser.prototype.getAge = ...会添加带有属性描述符的属性enumerable: true。这意味着它显示在for...in循环中。

for...in语句遍历对象的所有可枚举属性,这些属性以字符串为键(忽略以Symbol为键的),包括继承的可枚举属性

class User {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    getName() {
        console.log(this.name);
    }
}

User.prototype.getAge = function () {
    console.log(this.age);
};

let user = new User('john', 23);
let properties = [];

for (let prop in user) {
    properties.push(prop);
}

console.log(properties);

console.log(Object.getOwnPropertyDescriptor(User.prototype, "getName"));
console.log(Object.getOwnPropertyDescriptor(User.prototype, "getAge"));

如果您想以完全相同的方式定义原型,则必须使用相同的属性描述符。这可以通过以下方式实现Object.defineProperty()

Object.defineProperty(User.prototype, "getAge", {
    value: function () {
        console.log(this.age);
    },
    writable: true,
    enumerable: false,
    configurable: true,
});

推荐阅读