我有点困惑。
如果,例如......:
selection = Integer.parseInt(in.nextLine())
如果上面的说法正确并且我说得对,那么为什么我需要静态函数呢?因为这个:
function Person(firstName, lastName){
this.firstName = firstName;
this.lastName = lastName;
}
// so, the following will be shared, and this
// is the best practice, right?:
Person.prototype.whatEver = function(){
return this.firstName + " " + this.lastName;
}
// the following will also be shared, but it's
// bad practice, because it will be included in
// each instances and take space(memory) for nothing. correct?
Person.whatEver = function(){
return this.firstName + " " + this.lastName;
}
就是这样,对吗?:
Person.whatEver = function(){
return this.firstName + " " + this.lastName;
}
答案 0 :(得分:3)
虽然这相当于ES6静态方法,但它没有按照您的想法行事:
Person.whatEver = function(){
return this.firstName + " " + this.lastName;
}
这会将whatEver
函数放在Person
构造函数上,而不是放在实例化的person
上 - 而Person
构造函数可能没有firstName
或lastName
。你可能在考虑
const person = new Person();
person.whatEver = function(){
return this.firstName + " " + this.lastName;
}
在这种情况下,是的,每次Person实例化时都会运行这样的代码,这将导致很多函数(每个人一个),而不是原型上的单个函数。
静态方法的使用通常是 与实例化对象的交互。想想您何时可能需要与类关联的信息,即使尚未实例化任何内容。例如,您可以在Person类上使用静态方法:
class Person {
static canEat() {
return ['apples', 'bananas', 'carrots'];
}
// ...
答案 1 :(得分:1)
以下内容也将被分享,但这是不好的做法,因为它将被包含在每个实例中并且不占用空间(内存)。正确的吗?
不,不会。您会看到JS中的方法被指定为对它们的引用。此方法将创建一次,不会对每个对象反复重复。他们会指出相同的方法。这只是一种静态方法。因此,whatEver
函数的两个定义都是在Person类上静态定义它。
所以如果您有以下代码:
let firstPerson = new Person();
let secondPerson = new Person();
这两个对象都将引用相同的实例方法(原型1)whatEver
。现在,Person.whatEver
静态方法也将只有一个副本,只能在Person
类上直接调用,而且没有此类的实例。
答案 2 :(得分:1)
//contstructor
function Person () { … }
//member method
Person.prototype.foo = function () {
console.log(this);
}
//static method
Person.foo = function () {
console.log(this);
}
所有功能定义仅在内存中创建一次。差异是»这个背景«:
new Person().foo(); // [Object Person] or Person {}
Person.foo(); // Person () {}
这就是为什么你不能在静态函数中访问成员属性的原因。 this
指的是不是实例的构造函数。在幕后,使用new
运算符将执行以下操作:
var obj = Person.call({}) // a new Object is created and passed as the
// »this context« and automatically returned.
如果你有:
function Person () {
this.bar = function () { … }
}
将在Memory中为每个实例(new Person()
)创建一个新的函数对象,但这是原型链的特定属性。在实例上调用方法将导致JS解释器首先搜索所有“自己的”属性,然后上传原型链以查找所请求的属性。 prototype
由所有实例共享,因此其属性仅创建一次。
在ES6中,它看起来像这样:
class Person(){
static foo () {}
constructor () {}
bar () {}
}
答案 3 :(得分:1)
以下内容也将被分享,但这是不好的做法, 因为它将包含在每个实例中并采取 空间(记忆)什么都没有。正确的吗?
这是因为误解了函数在Javascript中的工作原理。
在基于class
的语言中,当创建类的实例时,所有方法定义(包括继承的方法定义)都被复制。
Javascript不是基于class
。
ES6添加了class
支持,但它只是一个糖,javascript class
并不像Java或C ++中的类(或大多数其他{{1} } ic语言)
class
方法并不需要实例化,这可能非常有用。
在Javascript中,由于没有类或类的实例化,因此不会复制这些方法。 只复制对函数的引用。
在您的代码中
static
为了便于理解,您可以将Person.whatEver = function(){
return this.firstName + " " + this.lastName;
}
视为具有函数Person
的对象。所以你的静态'
whatEver
例如,您可以在没有实例化的情况下调用let Person = {
whatEver() {
return this.firstName + " " + this.lastName;
},
talk() {
return 'I can talk';
},
};
。
但是,对于Person.talk()
函数,如果您需要访问其中的whatEver()
,将它声明为静态函数并不是一个好主意,因为假设是{ {1}}指向实例化的对象。
类模型不能很好地适应javascript,而且混淆通常源于此。
我想再补充一点:
this
事实并非如此。 Javascript中的所有函数都是共享的,this
和// so, the following will be shared, and this
// is the best practice, right?:
Person.prototype.whatEver = function(){
return this.firstName + " " + this.lastName;
}
只是声明函数的两种不同方式。
Person.prototype.whatEver
创建的对象调用 Person.whatEver
,这是一个构造函数调用。我的意思是当使用Person.prototype.whatEver
调用函数时,会创建一个空对象,new Person(..)
绑定到这个新对象,并且对象获得new
- 链接到{{1} }。
因此,当您将其this
实例化,并调用prototype
时,它会尝试在原型链中找到Person
函数引用,并会找到var p = new Person(..)
中有一个被调用。