由对象状态参数化的方法的实例方法与原型方法

问题描述 投票:0回答:1

tl;博士

优先选择原型方法而不是实例方法的建议是一般性的建议,还是仅适用于所讨论的方法确实独立于其他实例属性的情况?

或者,换句话说,如果我希望使用实例方法,因为我希望这样的方法由调用它的单个对象参数化,那么我是否错误设计了我的 JavaScript 应用程序,因为有更好的方法来实现这一点(即依赖于对象状态的方法,例如其实例变量)?


加长版

JavaScript Ninja 的秘密 - 第二版的第 7.2.1 节中,解释了定义实例方法之间的区别

function Ninja() {
  this.swung = false;
  this.swingSword = function() {
    return 'swing';
  };
}

const n1 = new Ninja();
const n2 = new Ninja();

console.log(n1.swingSword())
console.log(n2.swingSword())

与定义原型方法

function Ninja() {
  this.swung = false;
}
Ninja.prototype.swingSword = function() {
  return 'swing';
}

const n1 = new Ninja();
const n2 = new Ninja();

console.log(n1.swingSword())
console.log(n2.swingSword())

除了如果两者都被定义,则前者优先的事实之外,还声称前者也会带来性能损失(至少在创建的对象数量足够大的情况下),因为该方法的新副本将为每个

new Ninja()
调用创建。

我明白这一点,但这种说法并不意味着适用于这个简单的玩具示例,而是提供一般指导(至少这是我解释本书文本的方式!),而且我不明白为什么会这样应该是这样的。

确实,我忍不住想到一个稍微复杂一点的例子,其中构造函数有一些参数,这些参数是由实例方法的闭包捕获的,这意味着实际上每个对象的函数都是不同的:

function Ninja(foo) {
  this.swung = foo;
  this.swingSword = function() {
    return foo;
  };
}

const n1 = new Ninja('one');
const n2 = new Ninja('two');

console.log(n1.swingSword()) // this calls function() { return 'one'; };
console.log(n2.swingSword()) // this calls function() { return 'two'; };

在这种情况下,我认为原型方法不是一个选择,因为它在整个对象中是通用的,所以它不能由每个对象自定义,不是吗?

这也适用于成员变量,例如最后一个示例中的

swung
必须是实例属性,但在原始示例中很可能是原型属性,因为它只是
false
,它不会改变。

function Ninja() {}
Ninja.prototype.swung = false;
Ninja.prototype.swingSword = function() {
  return 'swing';
}

const n1 = new Ninja();
const n2 = new Ninja();

console.log(n1.swung)
console.log(n2.swung)

javascript oop inheritance ecmascript-6 prototypal-inheritance
1个回答
-2
投票

从 ES 6 开始,您可以使用类。 JavaScript 中的类基于原型构建,但也具有一些类特有的语法和语义。

class Person {
    #name;

    constructor(name) {
        this.#name = name;
    }

    sayName() {
        console.log(this.#name);
    }
}

const bob = new Person("Bob");
const bill = new Person("Bill");

bob.sayName();
bill.sayName();
© www.soinside.com 2019 - 2024. All rights reserved.