私はこれがうまくいくことを知っています:
function Foo() {};
Foo.prototype.talk = function () {
alert('hello~\n');
};
var a = new Foo;
a.talk(); // 'hello~\n'
でも電話したいのなら
Foo.talk() // this will not work
Foo.prototype.talk() // this works correctly
Foo.talk
を機能させる方法がいくつかあります。
Foo.__proto__ = Foo.prototype
Foo.talk = Foo.prototype.talk
これを行う他の方法はありますか?それが正しいかどうかはわかりません。 JavaScriptコードでクラスメソッドと静的メソッドのどちらを使用しますか?
まず、JavaScriptは主に クラスベース言語 ではなく プロトタイプ言語 です。1。 Foo
はクラスではなく、関数で、オブジェクトです。標準のOOP言語のクラスに似たものを作成できるようにするnew
キーワードを使用して、その関数 from をインスタンス化できます。
私はほとんどの場合__proto__
を無視することをお勧めします。ブラウザー間のサポートが不十分で、代わりにprototype
がどのように機能するのかを学ぶことに集中するためです。
関数から作成したオブジェクトのインスタンスがある場合2 そして、そのメンバー(メソッド、属性、プロパティ、定数など)のいずれかにアクセスすると、(a)メンバーが見つかるか、(b)別のプロトタイプが見つからなくなるまで、プロトタイプの階層を下っていきます。
階層は呼び出されたオブジェクトから始まり、そのプロトタイプオブジェクトを検索します。プロトタイプオブジェクトにプロトタイプがある場合は、それが繰り返されます。プロトタイプが存在しない場合はundefined
が返されます。
例えば:
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
私は、これらの「基本」部分を少なくともある程度理解しているように思えますが、念のために明示的にする必要があります。
JavaScriptでは、すべてがオブジェクトです3。
everythingはオブジェクトです。
function Foo(){}
は新しい関数を定義するだけではなく、Foo
を使ってアクセスできる新しい関数オブジェクトを定義します。
Foo.prototype
を使ってFoo
のプロトタイプにアクセスできるのはこのためです。
Foo
に more functions を設定することもできます。
Foo.talk = function () {
alert('hello world!');
};
この新しい機能は、以下を使用してアクセスできます。
Foo.talk();
関数オブジェクトと静的メソッドの関数間の類似性に気付いていることを今では願っています。
f = new Foo();
をクラスインスタンスの作成、Foo.prototype.bar = function(){...}
をクラスの共有メソッドの定義、Foo.baz = function(){...}
をクラスのパブリック静的メソッドの定義とします。
ECMAScript 2015では、これらの種類の宣言に対して、読みやすくしながらも実装を簡単にするためのさまざまな構文糖を導入しました。したがって、前の例は次のように書くことができます。
class Foo {
bar() {...}
static baz() {...}
}
これにより、bar
を次のように呼び出すことができます。
const f = new Foo()
f.bar()
baz
は次のように呼び出されます。
Foo.baz()
1: class
はECMAScript 5仕様の「Future Reserved Word」 ですが、ES6ではclass
キーワードを使用してクラスを定義する機能が導入されました。
2:基本的にコンストラクタによって作成されたクラスインスタンスですが、誤解させたくない微妙な違いがたくさんあります
3: プリミティブな値 - undefined
、null
、booleans、number、およびstringsを含みます。これらは低レベルの言語実装であるため、技術的には目的とされていません。ブール値、数値、および文字列は、あたかもオブジェクトであるかのようにプロトタイプチェーンと対話します。したがって、この回答の目的のためには、たとえそれらが「オブジェクト」であると考えてもしなくても簡単です。
あなたは以下のようにそれを達成することができます:
function Foo() {};
Foo.talk = function() { alert('I am talking.'); };
以下のようにして、 "talk"機能を呼び出すことができます。
Foo.talk();
JavaScriptでは、関数もオブジェクトであるため、これを実行できます。 "zzzzBov"もそれに答えました、しかしそれは長い読みです。
インスタンスから静的メソッドを呼び出します。
function Clazz() {};
Clazz.staticMethod = function() {
alert('STATIC!!!');
};
Clazz.prototype.func = function() {
this.constructor.staticMethod();
}
var obj = new Clazz();
obj.func(); // <- Alert's "STATIC!!!"
単純なJavaScriptクラスプロジェクト: https://github.com/reduardo7/sjsClass
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
さらに、今ではclass
とstatic
を使って処理することが可能です。
'use strict'
class Foo {
static talk() {
console.log('talk')
};
speak() {
console.log('speak')
};
};
あげる
var a = new Foo();
Foo.talk(); // 'talk'
a.talk(); // err 'is not a function'
a.speak(); // 'speak'
Foo.speak(); // err 'is not a function'
私は名前空間を使います:
var Foo = {
element: document.getElementById("id-here"),
Talk: function(message) {
alert("talking..." + message);
},
ChangeElement: function() {
this.element.style.color = "red";
}
};
そしてそれを使う:
Foo.Talk("Testing");
または
Foo.ChangeElement();
ES6は魅力のように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";
}
}
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 ;)");
};
@ https://abdulapopoola.com/2013/03/30/static-and-instance-methods-in-javascript/ を参照してください。
ちょっとしたメモ。 ES6クラスを使用して、スタティックメソッドを作成した場合.. Javacsriptエンジンは、ディスクリプタ属性を古い学校の "static"メソッドとは少し異なる設定にしました
function Car() {
}
Car.brand = function() {
console.log('Honda');
}
console.log(
Object.getOwnPropertyDescriptors(Car)
);
brand()の内部属性(descriptorプロパティ)を
..
brand: [object Object] {
configurable: true,
enumerable: true,
value: ..
writable: true
}
..
に比べ
class Car2 {
static brand() {
console.log('Honda');
}
}
console.log(
Object.getOwnPropertyDescriptors(Car2)
);
brand()の内部属性を
..
brand: [object Object] {
configurable: true,
enumerable: false,
value:..
writable: true
}
..
eS6の静的メソッドでは、enumerableがfalseに設定されていることを確認してください。
つまり、for-inループを使ってオブジェクトをチェックすることはできません。
for (let prop in Car) {
console.log(prop); // brand
}
for (let prop in Car2) {
console.log(prop); // nothing here
}
eS6の静的メソッドは、他のクラスのプライベートプロパティ(名前、長さ、コンストラクタ)と同様に扱われます。ただし、静的メソッドはまだ書き込み可能であるため、ディスクリプタ書き込み可能はtrue{ writable: true }
に設定されます。それはまた私達がそれを無効にできることを意味します
Car2.brand = function() {
console.log('Toyota');
};
console.log(
Car2.brand() // is now changed to toyota
);
Foo.talk
を呼び出そうとすると、JSは__proto__
を介して関数talk
を検索しようとしますが、もちろん、見つかりません。
Foo.__proto__
はFunction.prototype
です。
そのような状況に直面したとき、私はこのようなことをしました:
Logger = {
info: function (message, tag) {
var fullMessage = '';
fullMessage = this._getFormatedMessage(message, tag);
if (loggerEnabled) {
console.log(fullMessage);
}
},
warning: function (message, tag) {
var fullMessage = '';
fullMessage = this._getFormatedMessage(message, tag);
if (loggerEnabled) {
console.warn(fullMessage);`enter code here`
}
},
_getFormatedMessage: function () {}
};
だから今私はLogger.info("my Msg", "Tag");
としてinfoメソッドを呼び出すことができます
静的メソッド呼び出しはクラスで直接行われ、クラスのインスタンスでは呼び出せません。多くの場合、静的メソッドは効用関数を作成するために使用されます
かなり明確な説明
Fooはあなたのクラスに束縛される必要がありますそれであなたが新しいインスタンスを作成するときあなたはmyNewInstance.foo()を呼び出すことができますあなたがあなたのクラスをインポートするならあなたは静的メソッドを呼び出すことができます
Javascriptには実際のクラスはなく、むしろプロトタイプチェーンを介して他のオブジェクトからオブジェクトを「継承」するプロトタイプ継承システムを使用しています。これはコード自体で最もよく説明されます。
function Foo() {};
// creates a new function object
Foo.prototype.talk = function () {
console.log('hello~\n');
};
// put a new function (object) on the prototype (object) of the Foo function object
var a = new Foo;
// When foo is created using the new keyword it automatically has a reference
// to the prototype property of the Foo function
// We can show this with the following code
console.log(Object.getPrototypeOf(a) === Foo.prototype);
a.talk(); // 'hello~\n'
// When the talk method is invoked it will first look on the object a for the talk method,
// when this is not present it will look on the prototype of a (i.e. Foo.prototype)
// When you want to call
// Foo.talk();
// this will not work because you haven't put the talk() property on the Foo
// function object. Rather it is located on the prototype property of Foo.
// We could make it work like this:
Foo.sayhi = function () {
console.log('hello there');
};
Foo.sayhi();
// This works now. However it will not be present on the prototype chain
// of objects we create out of Foo
あなたのケースでは、あなたがFoo.talk()
したい場合:
function Foo() {};
// But use Foo.talk would be inefficient
Foo.talk = function () {
alert('hello~\n');
};
Foo.talk(); // 'hello~\n'
しかし、prototype
を使用するのがより効果的です。
別の方法では、私の方法は静的クラスとして定義されています。
var Foo = new function() {
this.talk = function () {
alert('hello~\n');
};
};
Foo.talk(); // 'hello~\n'
上記の静的クラスはprototype
を使用する必要はありません。静的な使用法として一度だけ作成されるからです。
https://github.com/yidas/js-design-patterns/tree/master/class