是否可以使用如下所示的语句来定义不使用prototype
的方法?
Person.sayHello = function () {...}
在这个例子中
var Person = function (firstName) {
this.firstName = firstName;
};
Person.prototype.sayHello = function() {
console.log("Hello, I'm " + this.firstName);
};
var person1 = new Person("Alice");
var person2 = new Person("Bob");
答案 0 :(得分:4)
简而言之,没有。
Person.sayHello = function () {...};
这一行将向Person类本身添加一个名为“sayHello”的函数,而不是Person类的实例。所以,它只能由
调用Person.sayHello();
而不是
var matt = new Person('Matt');
matt.sayHello();
// sayHello is not defined on matt
如果您熟悉Java或C#,以这种方式向Person添加方法就像创建静态方法一样。
但是,我们可以在不向原型添加方法的情况下向实例添加方法。
方法1:在Person的构造函数中创建“sayHello”函数
var Person = function (firstName) {
this.firstName = firstName;
this.sayHello = sayHello() {...};
};
此方法的缺点是为Person的每个实例创建了一个新函数。也就是说,
var frank = new Person('Frank');
var matt = new Person('Matt');
// frank.sayHello != matt.sayHello;
因此,这种方法对记忆力很难。但是,它确实允许通过闭包进行封装(例如私有状态)。在下面的示例中,如果不调用“sayHello”函数,则无法修改Person类之外的“count”变量。
var Person = function (firstName) {
this.firstName = firstName;
this.sayHello = sayHello() {
count++;
console.log("Hello has been said " + count + "times".
};
var count = 0;
};
方法2:在Person的构造函数外创建“sayHello”函数,并在Person的构造函数中指定它
var Person = function (firstName) {
this.firstName = firstName;
this.sayHello = sayHello;
};
function sayHello() {...}
此方法具有内存使用率较低的优点; sayHello函数只有一个实例,它在Person的实例之间共享。也就是说,
var frank = new Person('Frank');
var matt = new Person('Matt');
// frank.sayHello == matt.sayHello;
这使它类似于原型方法。但是,为每个实例分配函数仍然比原型方法消耗更多的内存,而原型方法只将函数分配给原型对象。
但是,与原型方法一样,此方法不允许私有状态。必须通过this
关键字公开的公共状态访问所有州。
更新:澄清方法1和方法2之间内存使用量的差异。
方法1是这样的:
var function1 = function() { console.log('Hello'); };
var function2 = function() { console.log('Hello'); };
函数具有相同的行为,但不相等。 JavaScript不知道它们在功能上是相似的,因此它在内存中创建了两个函数来表示它们。
方法2是这样的:
var sayHello = function() { console.log('Hello'); };
var function1 = sayHello;
var function2 = sayHello;
现在,function1和function2实际上是同一个函数,因为它们都只是持有对sayHello的引用。
更新:模块模式的示例用法,以避免在方法2中向全局范围添加“sayHello”。
此模块在由匿名闭包(自执行函数)定义的模块中定义Person类,并将其导出到全局范围。因为“sayHello”是在模块的闭包中定义的而不是导出的,所以它不会被添加到全局范围。
var Person = (function () {
function Person(firstName) {
this.firstName = firstName;
this.sayHello = sayHello;
};
function sayHello() {...}
return Person;
}());
答案 1 :(得分:0)
是的,你可以。如果你来自传统的OO背景,那么可能有助于将其视为有效地表现为类上的公共静态属性。
正如jsdeveloper在上述评论中所说。函数只是可以执行的对象。您可以像添加任何其他对象一样向它们添加属性。实际上,这种技术用于记忆或干扰等模式。
在您的情况下sayHello
可以在任何可以访问Person功能的地方访问。它与继承/原型并不真正相关,因为它与通过遍历原型链解析属性无关,但它是另一种使数据可访问的方法。
我确信它会因开发人员的不同而有所不同,但我经常把不引用this
的纯函数作为静态方法,因为它们更容易测试,并且明确其他意图开发者
答案 2 :(得分:-1)
这很奇怪,但是如果你真的需要这样做,你可以将函数分配给它自己的原型一次,然后将所有函数添加到main函数中。
var Person = function (firstName) {
this.firstName = firstName;
};
Person.prototype = Person;
Person.sayHello = function() {
console.log("Hello, I'm " + this.firstName);
};
答案 3 :(得分:-3)
是的,你可以,但是sayhello函数将无法访问任何对象属性(即this.myvar),你只能像静态方法一样调用它:
Person.sayhello()
(而不是mypersonobject.sayhello)。
扩展原型时,sayhello函数可用于以通常方式使用“new”关键字创建的所有Person对象。