[英]ES6 static method vs non-static and ES5 OOP
I'm a bit confused. 我有点困惑。
If, for example...: 如果,例如...:
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;
}
if the above correct and I got this right, then why the hell would I ever need a static functions? 如果上面的说法正确并且我说得对,那么为什么我需要静态函数? because this:
因为这:
Person.whatEver = function(){
return this.firstName + " " + this.lastName;
}
is exactly as this, correct?: 就是这样,对吗?:
// it would need to be inside of the class, of course
static whatEver(){
return this.firstName + " " + this.lastName;
}
While this is equivalent to an ES6 static method, it's not doing what you think: 虽然这相当于ES6静态方法,但它并没有按照您的想法进行:
Person.whatEver = function(){
return this.firstName + " " + this.lastName;
}
That puts the whatEver
function on the Person
constructor , not on an instantiated person
- and the Person
constructor probably does not have a firstName
or lastName
. 这将
whatEver
函数放在Person
构造函数上,而不是放在实例化的person
- 而Person
构造函数可能没有firstName
或lastName
。 You were probably thinking of 你可能在考虑
const person = new Person();
person.whatEver = function(){
return this.firstName + " " + this.lastName;
}
in which case, yes, running code like that every time a Person is instantiated will result in lots of functions (one for each person) rather than just a single function on the prototype. 在这种情况下,是的,每次实例化Person时都会运行这样的代码,这将导致许多函数(每个人一个),而不是原型上的单个函数。
The use for static methods is generally outside of interactions with instantiated objects. 静态方法的使用通常不在与实例化对象的交互之外 。 Think of when you might want information associated with a class even if nothing has necessarily been instantiated yet.
想想您何时可能需要与类关联的信息,即使尚未实例化任何内容。 For example, you could have a static method on the Person class:
例如,您可以在Person类上使用静态方法:
class Person {
static canEat() {
return ['apples', 'bananas', 'carrots'];
}
// ...
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?
正确?
No it won't. 不,不会。 You see methods in JS are assigned as references to them.
您会看到JS中的方法被指定为对它们的引用。 This method will be created once and not be repeated again and again for each object.
此方法将创建一次,不会对每个对象反复重复。 They'll point to the same method.
他们会指出相同的方法。 This is a static method only.
这只是一种静态方法。 So both definitions of the
whatEver
function are statically defining it on the Person class. 因此,
whatEver
函数的两个定义都是在Person类上静态定义它。
So if you have code like: 所以如果你有像这样的代码:
let firstPerson = new Person();
let secondPerson = new Person();
Both of these objects will have reference to the same instance method(the prototype one) whatEver
. 这两个对象都将引用相同的实例方法(原型一)
whatEver
。 Now the Person.whatEver
static method will also have a single copy which can be called directly on the Person
class only and no instance of this class. 现在
Person.whatEver
静态方法也将有一个副本,只能在Person
类上直接调用,而且没有此类的实例。
//contstructor
function Person () { … }
//member method
Person.prototype.foo = function () {
console.log(this);
}
//static method
Person.foo = function () {
console.log(this);
}
All function definitions are created only once in Memory. 所有函数定义仅在Memory中创建一次。 The diffrence is the »this context«:
差异是»这个背景«:
new Person().foo(); // [Object Person] or Person {}
Person.foo(); // Person () {}
So that is why you cannot access member properties in a static function. 这就是为什么你不能在静态函数中访问成员属性的原因。
this
refers to the constructor function not to the instance. this
指的是构造函数而不是实例。 Under the hood, using the new
operator will do something like this: 在引擎盖下,使用
new
运算符将执行以下操作:
var obj = Person.call({}) // a new Object is created and passed as the
// »this context« and automatically returned.
If you would have: 如果你有:
function Person () {
this.bar = function () { … }
}
a new function object would created in Memory for each instance ( new Person()
), but that is the particular property of the prototype chain. 在Memory中为每个实例创建一个新的函数对象(
new Person()
),但这是原型链的特定属性。 Calling a method on an instance, will cause the JS interpreter to first search all »own« properties and than go up the prototype chain to find the requested property. 在实例上调用方法将导致JS解释器首先搜索所有“自己的”属性,然后上传原型链以查找所请求的属性。 The
prototype
is shared by all instances, so its properties are only created once. prototype
由所有实例共享,因此其属性仅创建一次。
In ES6 it would look like this: 在ES6中,它看起来像这样:
class Person(){
static foo () {}
constructor () {}
bar () {}
}
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?
正确?
This comes from the misunderstanding of how functions work in Javascript. 这来自于对Javascript中函数如何工作的误解。
In class
-based languages, when an instance of a class is created, all the method definitions, including the inherited ones, are copied . 在基于
class
的语言中,当创建类的实例时,将复制所有方法定义,包括继承的方法定义。
Javascript is not class
-based. Javascript不是基于
class
的。
ES6 added class
support, but it's only a sugar, and javascript class
doesn't exactly act like classes in Java or C++ (or most other class
ic languages) ES6增加了
class
支持,但它只是一个糖,javascript class
并不像Java或C ++(或大多数其他class
ic语言)中的class
static
methods in Java or C++ doesn't require instantiation, which could be quite useful. Java或C ++中的
static
方法不需要实例化,这可能非常有用。
In Javascript, since there is no such thing as a class, or instantiation of a class, the methods do not get copied. 在Javascript中,由于没有类或类的实例化,因此不会复制方法。 Only the reference to the function gets copied.
仅复制对函数的引用。
In your code 在你的代码中
Person.whatEver = function(){
return this.firstName + " " + this.lastName;
}
For easier understanding, you can think of Person
as an object with a function whatEver
. 为了便于理解,您可以将
Person
视为具有函数whatEver
的对象。 So your 'static' method above is not too different from 所以你上面的'静态'方法与之没有什么不同
let Person = {
whatEver() {
return this.firstName + " " + this.lastName;
},
talk() {
return 'I can talk';
},
};
For example, you can call Person.talk()
without instantiation. 例如,您可以在不实例化的情况下调用
Person.talk()
。
However, for your whatEver()
function, if you need to access this
in it, it's not a good idea to declare it as a static function, because the assumption is that this
points to the instantiated object. 然而,对于您的
whatEver()
函数,如果你需要访问this
它,这不是一个好主意,声明为静态函数,因为假设的是, this
指向实例化的对象。
Class models don't fit into javascript quite well, and the confusion often originates from that. 类模型不能很好地适应javascript,并且混淆通常源于此。
I want to add one more thing: 我想补充一点:
// so, the following will be shared, and this
// is the best practice, right?:
Person.prototype.whatEver = function(){
return this.firstName + " " + this.lastName;
}
This is not true. 这不是真的。 All functions in Javascript is shared, and
Person.prototype.whatEver
and Person.whatEver
are just two different ways of declaring functions. Javascript中的所有函数都是共享的,
Person.prototype.whatEver
和Person.whatEver
只是两种不同的声明函数的方式。
Person.prototype.whatEver
can be called on an object you create with new Person(..)
, which is a constructor call . 可以使用
new Person(..)
创建的对象上调用Person.prototype.whatEver
,这是一个构造函数调用 。 By this I mean when a function is called with new
, an empty object gets created, this
gets bound to this new object, and the object gets prototype
-linked to Person
. 我的意思是,当使用
new
调用函数时,会创建一个空对象, this
将绑定到这个新对象,并且该对象将获得prototype
- 链接到Person
。
So when you instantiate it like var p = new Person(..)
, and call p.whatEver()
, it will try to find whatEver(..)
function reference in the prototype chain, and will find one in Person.prototype
, which gets called. 所以当你像
var p = new Person(..)
一样实例化它,并调用p.whatEver()
,它会尝试在原型链中找到whatEver(..)
函数引用 ,并在Person.prototype
找到一个,被调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.