JavaScript 中的类与静态方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7694501/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:12:32  来源:igfitidea点击:

Class vs. static method in JavaScript

javascriptoop

提问by lostyzd

I know this will work:

我知道这会起作用:

function Foo() {};
Foo.prototype.talk = function () {
    alert('hello~\n');
};

var a = new Foo;
a.talk(); // 'hello~\n'

But if I want to call

但如果我想打电话

Foo.talk() // this will not work
Foo.prototype.talk() // this works correctly

I find some methods to make Foo.talkwork,

我找到了一些Foo.talk工作的方法,

  1. Foo.__proto__ = Foo.prototype
  2. Foo.talk = Foo.prototype.talk
  1. Foo.__proto__ = Foo.prototype
  2. Foo.talk = Foo.prototype.talk

Are there other ways to do this? I don't know whether it is right to do so. Do you use class methods or static methods in your JavaScript code?

还有其他方法可以做到这一点吗?我不知道这样做是否正确。您在 JavaScript 代码中使用类方法还是静态方法?

回答by zzzzBov

First off, remember that JavaScript is primarily a prototypal language, rather than a class-based language1. Fooisn't a class, it's a function, which is an object. You can instantiate an object fromthat function using the newkeyword which will allow you to create something similar to a class in a standard OOP language.

首先,请记住 JavaScript 主要是一种原型语言,而不是基于类的语言1Foo不是一个类,它是一个函数,它是一个对象。您可以使用关键字该函数实例化一个对象,new这将允许您创建类似于标准 OOP 语言中的类的东西。

I'd suggest ignoring __proto__most of the time because it has poor cross browser support, and instead focus on learning about how prototypeworks.

我建议__proto__大多数时候忽略它,因为它的跨浏览器支持很差,而是专注于了解prototype工作原理。

If you have an instance of an object created from a function2and you access one of its members (methods, attributes, properties, constants etc) in any way, the access will flow down the prototype hierarchy until it either (a) finds the member, or (b) doesn't find another prototype.

如果您有一个从函数2创建的对象实例,并且您以任何方式访问其成员之一(方法、属性、属性、常量等),则访问将沿着原型层次向下流动,直到它 (a) 找到成员,或 (b) 没有找到另一个原型。

The hierarchy starts on the object that was called, and then searches its prototype object. If the prototype object has a prototype, it repeats, if no prototype exists, undefinedis returned.

层次结构从被调用的对象开始,然后搜索其原型对象。如果原型对象有原型,则重复,如果不存在原型,undefined则返回。

For example:

例如:

foo = {bar: 'baz'};
console.log(foo.bar); // logs "baz"

foo = {};
console.log(foo.bar); // logs undefined

function Foo(){}
Foo.prototype = {bar: 'baz'};
f = new Foo();
console.log(f.bar);
// logs "baz" because the object f doesn't have an attribute "bar"
// so it checks the prototype
f.bar = 'buzz';
console.log( f.bar ); // logs "buzz" because f has an attribute "bar" set


It looks to me like you've at least somewhat understood these "basic" parts already, but I need to make them explicit just to be sure.

在我看来,您至少已经对这些“基本”部分有所了解,但为了确定起见,我需要将它们明确化。

In JavaScript, everything is an object3.

在 JavaScript 中,一切都是对象3

everythingis an object.

一切都是对象。

function Foo(){}doesn't just define a new function, it defines a new function object that can be accessed using Foo.

function Foo(){}不只是定义一个新函数,它还定义了一个可以使用Foo.

This is why you can access Foo's prototype with Foo.prototype.

这就是为什么您可以使用 访问Foo的原型Foo.prototype

What you can also do is set more functionson Foo:

你也可以做的是设置更多的功能Foo

Foo.talk = function () {
  alert('hello world!');
};

This new function can be accessed using:

可以使用以下方法访问此新功能:

Foo.talk();

I hope by now you're noticing a similarity between functions on a function object and a static method.

我希望现在您已经注意到函数对象上的函数和静态方法之间的相似性。

Think of f = new Foo();as creating a class instance, Foo.prototype.bar = function(){...}as defining a shared method for the class, and Foo.baz = function(){...}as defining a public static method for the class.

可以将其f = new Foo();视为创建类实例、Foo.prototype.bar = function(){...}为类定义共享方法以及为类Foo.baz = function(){...}定义公共静态方法。



ECMAScript 2015 introduced a variety of syntactic sugar for these sorts of declarations to make them simpler to implement while also being easier to read. The previous example can therefore be written as:

ECMAScript 2015 为这些类型的声明引入了各种语法糖,使它们更易于实现,同时也更易于阅读。因此,前面的例子可以写成:

class Foo {
  bar() {...}

  static baz() {...}
}

which allows barto be called as:

这允许bar被称为:

const f = new Foo()
f.bar()

and bazto be called as:

并被baz称为:

Foo.baz()


1: classwas a "Future Reserved Word" in the ECMAScript 5 specification, but ES6 introduces the ability to define classes using the classkeyword.

1:class是 ECMAScript 5 规范中的“未来保留字”,但 ES6 引入了使用class关键字定义类的能力。

2: essentially a class instance created by a constructor, but there are many nuanced differences that I don't want to mislead you

2:本质上是一个由构造函数创建的类实例,但是有很多细微差别我不想误导你

3: primitive values—which include undefined, null, booleans, numbers, and strings—aren't technically objects because they're low-level language implementations. Booleans, numbers, and strings still interact with the prototype chain as though they were objects, so for the purposes of this answer, it's easier to consider them "objects" even though they're not quite.

3:原始值——包括undefinednull、布尔值、数字和字符串——在技术上不是对象,因为它们是低级语言实现。布尔值、数字和字符串仍然像对象一样与原型链交互,因此就本答案而言,即使它们不完全是“对象”,也更容易将它们视为“对象”。

回答by Bipul

You can achieve it as below:

你可以实现它如下:

function Foo() {};

Foo.talk = function() { alert('I am talking.'); };

You can now invoke "talk" function as below:

您现在可以调用“talk”功能,如下所示:

Foo.talk();

You can do this because in JavaScript, functions are objects as well.

您可以这样做,因为在 JavaScript 中,函数也是对象。

回答by Eduardo Cuomo

Call a static method from an instance:

从实例调用静态方法:

function Clazz() {};
Clazz.staticMethod = function() {
    alert('STATIC!!!');
};

Clazz.prototype.func = function() {
    this.constructor.staticMethod();
}

var obj = new Clazz();
obj.func(); // <- Alert's "STATIC!!!"

Simple Javascript Class Project: https://github.com/reduardo7/sjsClass

简单的Javascript类项目:https: //github.com/redardo7/sjsClass

回答by Jaskey

Here is a good example to demonstrate how Javascript works with static/instance variables and methods.

这是一个很好的例子来演示 Javascript 如何与静态/实例变量和方法一起工作。

function Animal(name) {
    Animal.count = Animal.count+1||1;// static variables, use function name "Animal"
    this.name = name; //instance variable, using "this"
}

Animal.showCount = function () {//static method
    alert(Animal.count)
}

Animal.prototype.showName=function(){//instance method
    alert(this.name);
}

var mouse = new Animal("Mickey");
var elephant = new Animal("Haddoop");

Animal.showCount();  // static method, count=2
mouse.showName();//instance method, alert "Mickey"
mouse.showCount();//Error!! mouse.showCount is not a function, which is different from  Java

回答by Dima Fomin

In additions, now it is possible to do with classand static

此外,现在可以使用classstatic

'use strict'

class Foo {
 static talk() {
     console.log('talk')
 };

 speak() {
     console.log('speak')
 };

};

will give

会给

var a = new Foo();
Foo.talk();  // 'talk'
a.talk();    // err 'is not a function'
a.speak();   // 'speak'
Foo.speak(); // err 'is not a function'

回答by A-Sharabiani

I use namespaces:

我使用命名空间:

var Foo = {
     element: document.getElementById("id-here"),

     Talk: function(message) {
            alert("talking..." + message);
     },

     ChangeElement: function() {
            this.element.style.color = "red";
     }
};

And to use it:

并使用它:

Foo.Talk("Testing");

Or

或者

Foo.ChangeElement();

回答by Abdennour TOUMI

ES6 supports now class& statickeywords like a charm :

ES6 支持 now class&static关键字之类的魅力:

class Foo {
    constructor() {}

    talk() {
        console.log("i am not static");
    }

    static saying() {
        console.log(this.speech);
    }

    static get speech() {
        return "i am static method";
    }

}

回答by Combine

If you have to write static methods in ES5 I found a great tutorial for that:

如果您必须在 ES5 中编写静态方法,我找到了一个很棒的教程:

//Constructor
var Person = function (name, age){
//private properties
var priv = {};

//Public properties
this.name = name;
this.age = age;

//Public methods
this.sayHi = function(){
    alert('hello');
}
}


// A static method; this method only 
// exists on the class and doesn't exist  
// on child objects
Person.sayName = function() {
   alert("I am a Person object ;)");  
};

see @https://abdulapopoola.com/2013/03/30/static-and-instance-methods-in-javascript/

见@ https://abdulapopoola.com/2013/03/30/static-and-instance-methods-in-javascript/

回答by ngakak

Just additional notes. Using class ES6, When we create static methods..the Javacsript engine set the descriptor attribute a lil bit different from the old-school "static" method

只是补充说明。使用 ES6 类,当我们创建静态方法时……Javacsript 引擎将描述符属性设置为与旧式“静态”方法略有不同

function Car() {

}

Car.brand = function() {
  console.log('Honda');
}

console.log(
  Object.getOwnPropertyDescriptors(Car)
);

it sets internal attribute (descriptor property) for brand() to

它将brand() 的内部属性(描述符属性)设置为

..
brand: [object Object] {
    configurable: true,
    enumerable: true,
    value: ..
    writable: true

}
..

compared to

相比

class Car2 {
   static brand() {
     console.log('Honda');
   }
}

console.log(
  Object.getOwnPropertyDescriptors(Car2)
);

that sets internal attribute for brand() to

将brand()的内部属性设置为

..
brand: [object Object] {
    configurable: true,
    enumerable: false,
    value:..
    writable: true
  }

..

see that enumerableis set to falsefor static method in ES6.

看到在 ES6 中,静态方法的enumerable设置为false

it means you cant use the for-in loop to check the object

这意味着您不能使用 for-in 循环来检查对象

for (let prop in Car) {
  console.log(prop); // brand
}

for (let prop in Car2) {
  console.log(prop); // nothing here
}

static method in ES6 is treated like other's class private property (name, length, constructor) except that static method is still writable thus the descriptor writableis set to true{ writable: true }. it also means that we can override it

ES6 中的静态方法被视为其他类的私有属性(名称、长度、构造函数),除了静态方法仍然是可写的,因此描述符writable被设置为true{ writable: true }。这也意味着我们可以覆盖它

Car2.brand = function() {
   console.log('Toyota');
};

console.log(
  Car2.brand() // is now changed to toyota
);

回答by Dave Keane

Static method calls are made directly on the class and are not callable on instances of the class. Static methods are often used to create utility function

静态方法调用直接在类上进行,不能在类的实例上调用。静态方法通常用于创建效用函数

Pretty clear description

描述很清楚

Taken Directly from mozilla.org

直接取自 mozilla.org

Foo needs to be bound to your class Then when you create a new instance you can call myNewInstance.foo() If you import your class you can call a static method

Foo 需要绑定到你的类然后当你创建一个新实例时你可以调用 myNewInstance.foo() 如果你导入你的类你可以调用一个静态方法