【问题标题】:Should we include methods in prototypes for ES6 Classes for performance?我们是否应该在 ES6 类的原型中包含方法以提高性能?
【发布时间】:2020-01-15 15:39:47
【问题描述】:

所以当我了解更多关于 JS 中的Prototypal Inheritance 时,我在MDN 文章中阅读了以下内容(阅读此链接上方的行)

请注意,当我们调用构造函数时,我们每次都在定义 greeting(),这并不理想。为了避免这种情况,我们可以在原型上定义函数,我们稍后会看到。

推荐的想法是在函数上添加properties,在prototype上添加methods(阅读here

Person.prototype.farewell = function() {
  alert(this.name.first + ' has left the building. Bye for now!');
};

我在很多地方都是这样阅读的

  • 对象创建速度更快,因为farewell 不是为每个对象创建创建的。这是因为它被创建一次并附加到prototype,并且所有对象链接prototype

  • prototypal chain 上查找方法,因此每个对象都链接到prototype 上的相同方法。

现在是 ES6 类。我有以下代码

class Person {
    constructor(first, last, age, gender, interests) {
        this.name = {
            first: first,
            last: last
        };
        this.age = age;
        this.gender = gender;
        this.interests = interests;
    }

    greeting () {
        console.log("Hi! I am", this.name.first);
    }

    farewell () {
        console.log(this.name.first, "has left the building. Bye for now!");
    }
}

似乎使用这种方法greetingfarewell 将被再次创建(遵循与函数相同的逻辑,因为class 是一种语法糖)

所以,我把班级改成

class Person {
    constructor(first, last, age, gender, interests) {
        this.name = {
            first: first,
            last: last
        };
        this.age = age;
        this.gender = gender;
        this.interests = interests;
    }
}

Person.prototype.greeting = function () {
    console.log("Hi! I am", this.name.first);
}

Person.prototype.farewell = function () {
    console.log(this.name.first, "has left the building. Bye for now!");
}

问题
1.后一种方式(在ES6 class中添加方法prototype)是推荐的方式吗?
2、class和传统new Function创建新对象的逻辑是否一致? CopyMethod on Prototype

如果还有什么我遗漏的,请告诉我

谢谢


更新

在几个答案之后,我重试了我的例子并确认了答案。我的代码看起来像

class Phone {
  constructor(company, name, color, price) {
    this.company = company;
    this.name = name;
    this.color = color;
    this.price = price;
  }

  print() {
    console.log(this.company, this.name, this.color, this.price);
  }
}

class Apple extends Phone {
    constructor(name, color, price) {
        super("Apple", name, color, price);
        this.companyWork = "ClosedSource";
    }
}

let iPhone11 = new Apple("iPhone11", "black", 900);
iPhone11.print()

运行此代码后,我可以确认print()Phone.prototype 上可用

【问题讨论】:

  • 这两个代码 sn-ps 做同样的事情。类方法是类原型对象的属性。
  • 谢谢@Paulpro,你能引用参考吗?
  • "似乎用这种方法会再次创建问候和告别" - 呃,不。它们没有放在constructor 中,它们位于class 语法中,这会将它们放在类的原型对象中。

标签: javascript class inheritance ecmascript-6 prototype


【解决方案1】:

阿法伊克

  1. 不,这不是推荐的方式。类方法被创建为原型上的方法。换句话说,类只是常规原型继承的语法糖。
  2. 在这两种情况下,如果创建了多个对象,则不会多次创建方法。方法只会被创建一次。

【讨论】:

  • 谢谢@krl,您能否引用“类方法作为原型方法创建”的参考。谢谢你。我尝试查找但找不到官方答案
  • @daydreamer 这个可以吗? ...class 关键字在 ES2015 中引入,但是是语法糖,JavaScript 仍然基于原型 developer.mozilla.org/en-US/docs/Web/JavaScript/…
【解决方案2】:

正如您已经发现的那样,class 定义将方法放在原型上。您要求提供参考,所以这里有一些您可以运行自己查看的小代码:

class Person {
    constructor(first, last, age, gender, interests) {
        this.name = {
            first: first,
            last: last
        };
        this.age = age;
        this.gender = gender;
        this.interests = interests;
    }

    greeting () {
        console.log("Hi! I am", this.name.first);
    }

    farewell () {
        console.log(this.name.first, "has left the building. Bye for now!");
    }
}

let p = new Person("Jack", "Beanstalk", 201, "giant", ["crushing things", "stomping things"]);

console.log("Person", Object.getOwnPropertyNames(Person));

console.log("p", Object.getOwnPropertyNames(p));

let p_prototype = Object.getPrototypeOf(p);

console.log("p_prototype === Person.prototype is ", p_prototype === Person.prototype);

console.log("Person.prototype", Object.getOwnPropertyNames(Person.prototype));

生成此输出:

Person [ 'length', 'prototype', 'name' ]
p [ 'name', 'age', 'gender', 'interests' ]
p_prototype === Person.prototype is true
Person.prototype [ 'constructor', 'greeting', 'farewell' ]

所以,你可以得出以下结论:

  1. Person 类只有构造函数和原型对象的预期属性,没有任何类定义的方法。

  2. 类的实例仅具有在构造函数中分配的预期数据属性,没有任何类定义的方法在对象本身上。

  3. 您从实例中获得的原型与类的原型相同(因此不会为每个实例创建新对象)。

  4. Person.prototype 具有来自 class 定义的预期方法以及指向构造函数本身的属性(用于继承和调用派生构造函数)。

因此,您可以从中验证使用 class 语法定义的方法在 Classname.prototype 对象上运行,并且该对象与所有实例共享。

【讨论】:

    猜你喜欢
    • 2015-06-04
    • 1970-01-01
    • 2020-11-15
    • 1970-01-01
    • 2015-05-22
    • 2015-03-28
    • 1970-01-01
    • 2012-05-28
    • 1970-01-01
    相关资源
    最近更新 更多