何时向原型添加成员?

When to add members to a prototype?

在下面的代码中,

function Stack() {
    this.stac = new Array();
    this.pop = function () {
        return this.stac.pop();
    }
    this.push = function (item) {
        this.stac.push(item);
    }
}

如何判断pushpopStackclass(如上所示)的实例成员还是Stack.prototype的成员?

如果你把它写在 class 里面,那个 class 的每个实例都会有自己的 pushpop 方法,因此您可以为每个实例重新定义这些方法。 如果您为原型定义这些方法,则所有实例都将共享这些方法。 因此,如果需要,您可以轻松地为每个实例更改 运行 上的那些方法。否则,您必须为每个先前创建的实例重写这些方法。 通过 原型 定义方法被认为是一种好的做法。它更快、更好并且使继承更容易!

检查Addy Osmany - Learning JavaScript Design Patterns

如果你想检查 属性 是来自原型还是来自实例,你可以使用这个: instanceName.hasOwnProperty(propertyName)

在你的例子中:

function Stack() {
    this.stac = new Array();
    this.pop = function () {
        return this.stac.pop();
    }
    this.push = function (item) {
        this.stac.push(item);
    }
}

Stack.prototype.notAnOwnProperty = 12;

var stack = new Stack();

console.log(stack.hasOwnProperty('pop'));
console.log(stack.hasOwnProperty('notAnOwnProperty'));

您将获得:

true
false

JSFiddle

要添加到@Lends 答案,当您想在另一个对象中继承该对象并在子对象中使用它们时,您还想向原型添加属性和方法。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Inheritance

在构造函数中定义的属性和方法是该对象的属性。这些不在实例之间共享。

简单的规则是

任何在 this 实例上添加到构造函数内部的东西都是该实例私有的

您可以使用 Object.is() 来比较不同的实例是否指向相同的方法。

您的代码:

function Stack() {
    this.stac = new Array();
    this.pop = function () {
        return this.stac.pop();
    }
    this.push = function (item) {
        console.log('In push');
        this.stac.push(item);
    }
}

var stack = new Stack(),
    stack2 = new Stack();
console.log(Object.is(stack.push, stack2.push)); // false

推荐方式:

建议在prototype上添加常用的共享属性和方法。这些属性和方法在对象实例之间共享。

function Stack2() {
    this.stack = new Array();
}
Stack2.prototype.pop = function () {
    return this.stack.pop();
};
Stack2.prototype.push = function (item) {
    console.log('In push');
    this.stack.push(item);
}
var stack = new Stack2(),
    stack2 = new Stack2();

console.log(Object.is(stack.push, stack2.push)); // true

继承意味着可重用性,如果需要,可以通过隐藏已编写的方法来自由覆盖功能。在上面的示例中,如果您想进一步 Inherit(Make Parrent Object) Stack 并希望为其继承的对象提供默认的 pushpop 功能,在这种情况下,您应该将 pushpopStack.prototype 中起作用。这将使继承对象(子对象)自由使用默认的 poppush 方法或覆盖这些方法(通过声明具有相同名称的新方法)。

有关Portotype Pattern的进一步参考,请关注 Prototype Pattern

在 pluralsight 上用例子解释 Using the JavaScript Prototype Pattern