JavaScriptの静的変数


716

JavaScriptで静的変数を作成するにはどうすればよいですか?


「dispaly:none」スタイル属性でラベルまたはその他のhtmlタグを定義し、この値の変数値とこの値の操作を設定できます。頑張らないでください。
asghar

私が見つけた最も簡単な解決策:クラスで静的変数をまったく定義しないでください。静的変数を使用したい場合は、そこに定義してから、たとえばを使用しsomeFunc = () => { MyClass.myStaticVariable = 1; }ます。次に、静的メソッドを作成して静的メンバーを返しstatic getStatic() { return MyClass.myStaticVariable; }ます。次にMyClass.getStatic()、クラスの外側から呼び出して静的データを取得できます。
Pixel

回答:


863

クラスベースの静的型付きオブジェクト指向言語(Java、C ++、C#など)を使用している場合、インスタンスではなく「型」に関連付けられた変数またはメソッドを作成しようとしていると思います。

コンストラクター関数を使用した「クラシック」アプローチを使用した例は、基本的なOO JavaScriptの概念を理解するのに役立つ可能性があります。

function MyClass () { // constructor function
  var privateVariable = "foo";  // Private variable 

  this.publicVariable = "bar";  // Public variable 

  this.privilegedMethod = function () {  // Public Method
    alert(privateVariable);
  };
}

// Instance method will be available to all instances but only load once in memory 
MyClass.prototype.publicMethod = function () {    
  alert(this.publicVariable);
};

// Static variable shared by all instances
MyClass.staticProperty = "baz";

var myInstance = new MyClass();

staticPropertyMyClassオブジェクト(関数)で定義され、作成されたインスタンスとは何の関係もありません。JavaScriptは関数をファーストクラスオブジェクトとして扱うため、オブジェクトであり、プロパティを関数に割り当てることができます。

更新: ES6では、キーワードを使用してクラス宣言する機能が導入されましたclass。これは、既存のプロトタイプベースの継承に対する構文糖衣です。

staticキーワードは、あなたが簡単にクラスの静的プロパティやメソッドを定義することができます。

ES6クラスで実装された上記の例を見てみましょう:

class MyClass {
  // class constructor, equivalent to
  // the function body of a constructor
  constructor() {
    const privateVariable = 'private value'; // Private variable at the constructor scope
    this.publicVariable = 'public value'; // Public property

    this.privilegedMethod = function() {
      // Public Method with access to the constructor scope variables
      console.log(privateVariable);
    };
  }

  // Prototype methods:
  publicMethod() {
    console.log(this.publicVariable);
  }

  // Static properties shared by all instances
  static staticProperty = 'static value';

  static staticMethod() {
    console.log(this.staticProperty);
  }
}

// We can add properties to the class prototype
MyClass.prototype.additionalMethod = function() {
  console.log(this.publicVariable);
};

var myInstance = new MyClass();
myInstance.publicMethod();       // "public value"
myInstance.additionalMethod(); // "public value"
myInstance.privilegedMethod(); // "private value"
MyClass.staticMethod();             // "static value"


5
おそらくprivilegedMethodそれはMyClassのインスタンスで呼び出すことができようにそれはそうなのでOOでプライベートメソッドと等価ではないでしょうか?アクセスできるので特権があるということですprivateVariableか?
ドナル・

3
this.constructor「インスタンスメソッド」から静的変数にアクセスするために使用できませんか?はいの場合は、回答に追加する価値があります。
Ciro Santilli冠状病毒审查六四事件法轮功

1
例では静的関数についても言及できます。
デビッドロドリゲス

18
こんにちは、この行に同意するかどうかはわかりません。//すべてのインスタンスで共有される静的変数 'MyClass.staticProperty = "baz";' 以下のように私の推論は、あなたはもちろんのどのあなたがすることはできません「myInstance.staticProperty」からバズ見つけることができるということ。
fullstacklife '19年

5
おそらくそれを読むMyClass.prototype.staticProperty = "baz";か、OOの原則に対してさらに正確にするために、静的プロパティは実際には無名関数として定義する必要がありMyClass.prototype.staticProperty = function () {return staticVar;}、すべてのインスタンスが1つの変数にアクセスできるようにします。
lindsaymacvean 2015年

535

JS関数もオブジェクトであるという事実を利用するかもしれません-つまり、それらはプロパティを持つことができます。

例えば、上で与えられた例を引用記事(現在は消滅し)JavaScriptで静的変数を

function countMyself() {
    // Check to see if the counter has been initialized
    if ( typeof countMyself.counter == 'undefined' ) {
        // It has not... perform the initialization
        countMyself.counter = 0;
    }

    // Do something stupid to indicate the value
    alert(++countMyself.counter);
}

その関数を数回呼び出すと、カウンターが増加していることがわかります。

そして、これはおそらく、グローバル変数でグローバル名前空間を汚染するよりもはるかに優れたソリューションです。


そして、これはクロージャに基づく別の可能な解決策ですJavaScriptで静的変数を使用するトリック

var uniqueID = (function() {
   var id = 0; // This is the private persistent value
   // The outer function returns a nested function that has access
   // to the persistent value.  It is this nested function we're storing
   // in the variable uniqueID above.
   return function() { return id++; };  // Return and increment
})(); // Invoke the outer function after defining it.

これにより、同じ種類の結果が得られます。ただし、今回は、表示されるのではなく、増分された値が返されます。


50
ショートカットとして、countMyself.counter = countMyself.counter || initial_value;静的変数がfalse(false、0、null、または空の文字列)にならない場合にのみ実行できます
Kip

3
少し短くて明確:(function(){var id = 0; function uniqueID(){return id ++;};})();
トムロビンソン

3
クロージャのカウンタは、Firefoxのクラスよりも非常に高速です。jsperf.com/static-counter-in-class-vs-in-closure
Sony Santos

チェックに使用===typeofないと、変な強制が行われます。
dewd、

@SonySantosあなたのテストはFirefox 40の反対を示しています
bartolo-otrit

96

これは、IIFE(すぐに呼び出される関数式)を通じて行います。

var incr = (function () {
    var i = 1;

    return function () {
        return i++;
    }
})();

incr(); // returns 1
incr(); // returns 2

21
これはJavaScriptでこれを行う最も慣用的な方法だと思います。残念なことに、他の言語を使用している人にとってはより口当たりのよい他の方法のおかげで、賛成票が多くなりすぎません。

1
単に「IIFE」ではなく「閉鎖」を使って言い換えます。
zendka

39

arguments.calleeを使用して「静的」変数を保存できます(これは無名関数でも役立ちます):

function () {
  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 1;
  arguments.callee.myStaticVar++;
  alert(arguments.callee.myStaticVar);
}

3
私が理解できる限り、この方法には、パスカルMARTINの方法に比べて1つ(1つだけ?)の利点があります。それは、匿名関数で使用できることです。この例は素晴らしいでしょう
Dan

27
arguments.callee廃止予定です。
Quolonelの質問2013

私はいつもJSをばかにしますが、callee持つのは良いことのように思えました。なぜハックはこれを廃止することにしたのか...:|
user2173353 2016

35

似たような回答をいくつか見ましたが、この投稿がそれを最もよく表していることを述べたいので、それを共有したいと思います。

これから抜粋したコードの一部を以下に示します。これは、クラスのデザインテンプレートとして使用できるため、コミュニティに利益をもたらすと期待される完全な例を取得するために変更しました。

それはまたあなたの質問に答えます:

function Podcast() {

    // private variables
    var _somePrivateVariable = 123;

    // object properties (read/write)
    this.title = 'Astronomy Cast';
    this.description = 'A fact-based journey through the galaxy.';
    this.link = 'http://www.astronomycast.com';

    // for read access to _somePrivateVariable via immutableProp 
    this.immutableProp = function() {
        return _somePrivateVariable;
    }

    // object function
    this.toString = function() {
       return 'Title: ' + this.title;
    }
};

// static property
Podcast.FILE_EXTENSION = 'mp3';
// static function
Podcast.download = function(podcast) {
    console.log('Downloading ' + podcast + ' ...');
};

この例では、次のように静的プロパティ/関数にアクセスできます。

// access static properties/functions
console.log(Podcast.FILE_EXTENSION);   // 'mp3'
Podcast.download('Astronomy cast');    // 'Downloading Astronomy cast ...'

そして、オブジェクトのプロパティ/関数は単に次のようになります:

// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString());       // Title: The Simpsons
console.log(podcast.immutableProp());  // 123

そのpodcast.immutablePropで()、我々はクロージャを _somePrivateVariableへの参照は、関数の内部で保持されます。

ゲッターとセッターを定義することもできます。次のコードスニペットを見てください(dプロパティを宣言するオブジェクトのプロトタイプyは、コンストラクターの外部からは見えないプライベート変数です)。

// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
    get: function() {return this.getFullYear() },
    set: function(y) { this.setFullYear(y) }
});

プロパティはd.yearvia getset関数を定義します-を指定しない場合set、プロパティは読み取り専用で変更できません(設定しようとしてもエラーは発生しませんが、効果はありません)。各プロパティには属性がありwritableconfigurable(宣言の後に変更することができます)とenumerable、デフォルトごとにある(列挙子としてそれを使用できるようにします)、 false。これらdefinePropertyは、3番目のパラメータ(など)で設定できますenumerable: true

次の構文も有効です。

// getters and setters - alternative syntax
var obj = { a: 7, 
            get b() {return this.a + 1;}, 
            set c(x) {this.a = x / 2}
        };

これは、読み取り/書き込み可能なプロパティa、読み取り専用プロパティb、および書き込み専用プロパティを定義します。cこれらのプロパティを通じてaアクセスできます。

使用法:

console.log(obj.a); console.log(obj.b); // output: 7, 8
obj.c=40;
console.log(obj.a); console.log(obj.b); // output: 20, 21

ノート:

newキーワードを忘れた場合の予期しない動作を回避するために、関数に以下を追加することをお勧めしますPodcast

// instantiation helper
function Podcast() {
    if(false === (this instanceof Podcast)) {
        return new Podcast();
    }
// [... same as above ...]
};

これで、次のインスタンス化の両方が期待どおりに機能します。

var podcast = new Podcast(); // normal usage, still allowed
var podcast = Podcast();     // you can omit the new keyword because of the helper

'new'ステートメントは、新しいオブジェクトを作成し、すべてのプロパティとメソッドをコピーします。

var a=new Podcast();
var b=new Podcast();
a.title="a"; b.title="An "+b.title;
console.log(a.title); // "a"
console.log(b.title); // "An Astronomy Cast"

また、状況によってreturnは、コンストラクター関数のステートメントを使用してPodcast、クラスが内部的に依存しているが公開する必要のある関数を保護するカスタムオブジェクトを返すと便利な場合があります。これについては、一連の記事の第2章(オブジェクト)で詳しく説明しています。

あなたはそれを言ってabから継承することができますPodcast。さて、何をした後、それらのすべてに適用されるポッドキャストへのメソッドを追加したい場合abインスタンス化されていますか?この場合、.prototype次のように使用します。

Podcast.prototype.titleAndLink = function() {
    return this.title + " [" + this.link + "]";
};

今すぐお電話ab再び:

console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"

プロトタイプの詳細については、こちらをご覧ください。より多くの継承をしたい場合は、これを調べることをお勧めします


上記の記事シリーズは、読むこと強くお勧めします。次のトピックも含まれます。

  1. 機能
  2. オブジェクト
  3. プロトタイプ
  4. コンストラクター関数に新しいを強制する
  5. 巻き上げ
  6. セミコロンの自動挿入
  7. 静的プロパティとメソッド

JavaScriptのセミコロン自動挿入「機能」(6で説明)は、コードで奇妙な問題を引き起こす原因となることが非常に多いことに注意してください。したがって、私はむしろそれを機能としてではなくバグと見なしたいと思います。

あなたがもっと読みたい場合は、ここでは非常に興味深いですMSDNの記事これらのトピックについて、それらのいくつかは、さらに多くの詳細が提供説明しました。

同じく興味深いのは(上記のトピックもカバーする)MDN JavaScriptガイドの記事です:

JavaScriptで(など)c#outパラメーターエミュレートする方法を知りたい場合はDateTime.TryParse(str, out result)ここでサンプルコードを見つけることができます


されているあなたの人々のIEでの作業(あなたが使用して開発ツールを開かない限りはJavaScriptのためのコンソールを持っていないF12し、コンソールタブを開くには)次のスニペットが役に立つかもしれません。console.log(msg);上記の例で使用されているように使用できます。Podcast関数の前に挿入するだけです。

便宜上、上記のコードを1つの完全な単一のコードスニペットで示します。


ノート:

  • JavaScriptプログラミング全般に関するいくつかの優れたヒント、ヒント、および推奨事項は、ここ(JavaScriptのベストプラクティス)そこ(「var」と「let」)にあります。暗黙の型キャスト(強制)に関するこの記事もお勧めし ます。

  • クラスを使用してJavaScriptにコンパイルする便利な方法はTypeScriptです。 遊び場は、それがどのように機能するかを示すいくつかの例を見つけることができます。現時点でTypeScriptを使用していない場合でも、TypeScriptとJavaScriptの結果を並べて表示して比較できるので、外観を確認できます。ほとんどの例は単純ですが、すぐに試すことができるレイトレーサーの例もあります。特に、「クラスの使用」、「継承の使用」、および「ジェネリックスの使用」の例をコンボボックスで選択して調べることをお勧めします。これらは、JavaScriptですぐに使用できる素晴らしいテンプレートです。TypescriptはAngularで使用されます。

  • 達成するためにカプセル化ローカル変数は、JavaScriptの関数などのを、私は(jQueryのと同じ手法を使用しています)、次のようなパターンを使用することをお勧め:

<html>
<head></head>
<body><script>
    'use strict';
    // module pattern (self invoked function)
    const myModule = (function(context) { 
    // to allow replacement of the function, use 'var' otherwise keep 'const'

      // put variables and function with local module scope here:
      var print = function(str) {
        if (str !== undefined) context.document.write(str);
        context.document.write("<br/><br/>");
        return;
      }
      // ... more variables ...

      // main method
      var _main = function(title) {

        if (title !== undefined) print(title);
        print("<b>last modified:&nbsp;</b>" + context.document.lastModified + "<br/>");        
        // ... more code ...
      }

      // public methods
      return {
        Main: _main
        // ... more public methods, properties ...
      };

    })(this);

    // use module
    myModule.Main("<b>Module demo</b>");
</script></body>
</html>

もちろん、スクリプトコードを別の*.jsファイルに配置することもできます。これは、例を短くするためにインラインで書かれているだけです。

自己呼び出し関数(IIFE =即時呼び出し関数式とも呼ばれます)については、ここで詳しく説明します


28
function Person(){
  if(Person.count == undefined){
    Person.count = 1;
  }
  else{
    Person.count ++;
  }
  console.log(Person.count);
}

var p1 = new Person();
var p2 = new Person();
var p3 = new Person();

28

更新された回答:

ECMAScript 6、あなたが使用してスタティック関数を作成することができますstaticキーワードを:

class Foo {

  static bar() {return 'I am static.'}

}

//`bar` is a property of the class
Foo.bar() // returns 'I am static.'

//`bar` is not a property of instances of the class
var foo = new Foo()
foo.bar() //-> throws TypeError

ES6クラスは、静的の新しいセマンティクスを導入しません。ES5では次のように同じことができます。

//constructor
var Foo = function() {}

Foo.bar = function() {
    return 'I am static.'
}

Foo.bar() // returns 'I am static.'

var foo = new Foo()
foo.bar() // throws TypeError

FooJavaScriptでは関数はオブジェクトなので、プロパティに割り当てることができます。


Foo.bar;割り当てられた関数を返します。コメントが示すように、関数によって返される文字列ではありません。

これらの両方の例で静的な値を設定(上書き)する方法に関する情報を追加できますか?
Wilt

1
@Wiltはどちらの場合も、「静的」プロパティは関数のプロパティにすぎないため、JavaScriptの他のプロパティと同じように設定して上書きします。どちらの場合も、あなたが設定できるbarの財産Fooにし3、次のように:Foo.bar = 3;
マックスHeiber


16

次の例と説明は、Nicholas Zakas著の本「Professional JavaScript for Web Developers 2nd Edition」から引用しています。これが私が探していた答えなので、ここに追加すると役立つと思いました。

(function () {
    var name = '';
    Person = function (value) {
        name = value;
    };
    Person.prototype.getName = function () {
        return name;
    };
    Person.prototype.setName = function (value) {
        name = value;
    };
}());
var person1 = new Person('Nate');
console.log(person1.getName()); // Nate
person1.setName('James');
console.log(person1.getName()); // James
person1.name = 'Mark';
console.log(person1.name); // Mark
console.log(person1.getName()); // James
var person2 = new Person('Danielle');
console.log(person1.getName()); // Danielle
console.log(person2.getName()); // Danielle

Personこの例のコンストラクタは、getName()およびsetName()メソッドと同様に、プライベート変数名にアクセスできます。このパターンを使用すると、name変数が静的になり、すべてのインスタンス間で使用されます。つまりsetName()、1つのインスタンスを呼び出すと、他のすべてのインスタンスに影響します。setName()新しいPersonインスタンスを呼び出すか作成すると、name変数に新しい値が設定されます。これにより、すべてのインスタンスが同じ値を返します。


コンストラクタ+プロトタイプ(ハイブリッド)に見える
ガネーシュクマー

2
これにより、Personオブジェクトがグローバル名前空間に配置されます。私がお勧めする解決策ではありません。
Ghola 2013年

新しいオブジェクトごとにインスタンス化が異なるため、これは本当の静的変数だとは思わない。静的オブジェクトは、親プロトタイプから継承するすべてのオブジェクトで一貫している必要がありますか?
lindsaymacvean 2015年

1
@Gholaここでの意図は、静的変数を作成する方法を説明することでした。適切なネームスペースとグローバルの回避は別のトピックであり、回答がさらに複雑になった可能性があります。汚染せずにコンストラクターをアタッチする方法を決定するのはユーザー次第です。ニコラス・ザカスにとってそれで十分であれば、私にとっても十分です。
2016年

@lindsaymacvean単一の値がすべてのインスタンスで共有されるため、これは静的変数です。値を変更しても問題ありません。1つのインスタンスが値を変更すると、すべてのインスタンスが影響を受けます。上記の例とまったく同じように使用される可能性は低いです。インスタンス化中に値を設定できるようにするのは、その可能性を示すためです。より可能性の高い使用例は、getterとsetterのみを使用するか、少なくとも未定義以外に設定されていることを確認することです。
2016年

15

新しいクラス構文を使用している場合は、次の操作を実行できます。

    class MyClass {
      static get myStaticVariable() {
        return "some static variable";
      }
    }

    console.log(MyClass.myStaticVariable);

    aMyClass = new MyClass();
    console.log(aMyClass.myStaticVariable, "is undefined");

これにより、JavaScriptで静的変数が効果的に作成されます。


これは、静的ユーティリティクラスを構築するときに役立ちます。
17

1
しかし、ここで問題は、値を永続化し、セッターを使用して値を変更できるようにする方法です。クロージャが必要になるかMyClass、クラスコンストラクトの外部で定義されたプロパティが必要になります。
トリンコット


8

アプリケーションで定数を作成するための静的変数を宣言したい場合は、最も単純なアプローチとして以下を見つけました

ColorConstants = (function()
{
    var obj = {};
    obj.RED = 'red';
    obj.GREEN = 'green';
    obj.BLUE = 'blue';
    obj.ALL = [obj.RED, obj.GREEN, obj.BLUE];
    return obj;
})();

//Example usage.
var redColor = ColorConstants.RED;

8

classECMAScript 2015によって導入されたものについて。他の答えは完全に明確ではありません。

ここでは、静的VAR作成する方法を示す例であるstaticVarとしますClassNamevarシンタックス:

class MyClass {
    constructor(val) {
        this.instanceVar = val;
        MyClass.staticVar = 10;
    }
}

var class1 = new MyClass(1);
console.log(class1.instanceVar);      // 1
console.log(class1.constructor.staticVar); // 10

// New instance of MyClass with another value
var class2 = new MyClass(3);
console.log(class1.instanceVar);      // 1
console.log(class2.instanceVar);      // 3

静的変数にアクセスするには、 .constructor、クラスを作成したオブジェクトコンストラクター関数への参照を返すプロパティます。作成した2つのインスタンスで呼び出すことができます。

MyClass.staticVar = 11;
console.log(class1.constructor.staticVar); // 11
console.log(class2.constructor.staticVar); // 11 <-- yes it's static! :)

MyClass.staticVar = 12;
console.log(class1.constructor.staticVar); // 12
console.log(class2.constructor.staticVar); // 12

7

他にも似たような答えはありますが、どれも私にとって魅力的ではありませんでした。これが私が終わったものです:

var nextCounter = (function () {
  var counter = 0;
  return function() {
    var temp = counter;
    counter += 1;
    return temp;
  };
})();

7

残りに加えて、クラスにパブリックフィールドを紹介するECMAプロポーザルに関するドラフト(ステージ2プロポーザル)が現在あります。(プライベートフィールドが考慮されましたstatic

提案の例を使用すると、提案されるstatic構文は次のようになります。

class CustomDate {
  // ...
  static epoch = new CustomDate(0);
}

そして、他の人が強調した以下のものと同等です:

class CustomDate {
  // ...
}
CustomDate.epoch = new CustomDate(0);

その後、からアクセスできますCustomDate.epoch

で新しい提案を追跡できproposal-static-class-featuresます。


現在、babelは、使用できる変換クラスプロパティプラグインでこの機能をサポートしています。さらに、まだ進行中V8ですが、実装しています。


6

以下のようにJavaScriptで静的変数を作成できます。これcountが静的変数です。

var Person = function(name) {
  this.name = name;
  // first time Person.count is undefined, so it is initialized with 1
  // next time the function is called, the value of count is incremented by 1
  Person.count = Person.count ? Person.count + 1 : 1;
}

var p1 = new Person('User p1');
console.log(p1.constructor.count);   // prints 1
var p2 = new Person('User p2');
console.log(p2.constructor.count);   // prints 2

Person関数またはインスタンスのいずれかを使用して、静的変数に値を割り当てることができます。

// set static variable using instance of Person
p1.constructor.count = 10;         // this change is seen in all the instances of Person
console.log(p2.constructor.count); // prints 10

// set static variable using Person
Person.count = 20;
console.log(p1.constructor.count); // prints 20

これは、静的変数を宣言してJavaScriptでアクセスするための優れたアプローチの1つです。
ArunDhwaj IIITH 2018

5

グローバル静的変数を作成したい場合:

var my_id = 123;

変数を以下に置き換えます。

Object.defineProperty(window, 'my_id', {
    get: function() {
            return 123;
        },
    configurable : false,
    enumerable : false
});

4

JavaScriptで静的変数に最も近いのはグローバル変数です。これは、関数またはオブジェクトリテラルのスコープ外で宣言された変数です。

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;
}

他にできることは、次のようなオブジェクトリテラル内にグローバル変数を格納することです。

var foo = { bar : 1 }

次に、次のように変数にアクセスしますfoo.bar


これは複数のファイルをアップロードするのに役立ちました..... var foo = {counter:1}; function moreFiles(){fileName = "File" + foo.counter; foo.counter = foo.counter + 1;
veer7

4

ここでクラスのすべての概念を要約するには、これをテストします。

var Test = function() {
  // "super private" variable, accessible only here in constructor. There are no real private variables
  //if as 'private' we intend variables accessible only by the class that defines the member and NOT by child classes
  var test_var = "super private";

  //the only way to access the "super private" test_var is from here
  this.privileged = function(){
    console.log(test_var);
  }();

  Test.test_var = 'protected';//protected variable: accessible only form inherited methods (prototype) AND child/inherited classes

  this.init();
};//end constructor

Test.test_var = "static";//static variable: accessible everywhere (I mean, even out of prototype, see domready below)

Test.prototype = {

 init:function(){
   console.log('in',Test.test_var);
 }

};//end prototype/class


//for example:
$(document).ready(function() {

 console.log('out',Test.test_var);

 var Jake = function(){}

 Jake.prototype = new Test();

 Jake.prototype.test = function(){
   console.log('jake', Test.test_var);
 }

 var jake = new Jake();

 jake.test();//output: "protected"

});//end domready

そうですね、これらのベストプラクティスを確認するもう1つの方法は、coffeescriptがこれらの概念をどのように変換するかを確認することです。

#this is coffeescript
class Test
 #static
 @prop = "static"

 #instance
 constructor:(prop) ->
   @prop = prop
   console.log(@prop)

 t = new Test('inst_prop');

 console.log(Test.prop);


//this is how the above is translated in plain js by the CS compiler
  Test = (function() {
    Test.prop = "static";

    function Test(prop) {
     this.prop = prop;
     console.log(this.prop);
    }

    return Test;

  })();

  t = new Test('inst_prop');

  console.log(Test.prop);

4

JavaScriptでは、変数はデフォルトで静的です。

var x = 0;

function draw() {
    alert(x); //
    x+=1;
}

setInterval(draw, 1000);

xの値は1000ミリ秒ごとに1ずつ増加し
ます。1、2、3と出力されます。


2
それは別のケースです。あなたの例はスコープについてです。
チャレット

4

このスレッドを閲覧した後、私の要件を解決する別のアプローチがあります。それは、「静的変数」で何を実現したいかによります。

グローバルプロパティのsessionStorageまたはlocalStorageを使用すると、セッションの存続期間中、または明示的にクリアされるまで、無期限に長期間データを保存できます。これにより、ページ/アプリのすべてのウィンドウ、フレーム、タブパネル、ポップアップなどでデータを共有できるようになり、1つのコードセグメントの単純な「静的/グローバル変数」よりもはるかに強力になります。

これは、トップレベルのグローバル変数、つまりWindow.myglobalのスコープ、有効期間、セマンティクス、ダイナミクスなどの面倒をすべて回避します。それがどれほど効率的であるかはわかりませんが、適度な速度でアクセスされる適度な量のデータにとっては重要ではありません。

「sessionStorage.mydata = Anything」として簡単にアクセスでき、同様に取得できます。「JavaScript:The Definitive Guide、Sixth Edition」、David Flanagan、ISBN:978-0-596-80552-4、第20章、セクション20.1を参照してください。これは、簡単な検索でPDFとして、またはO'Reilly Safaribooksサブスクリプション(金でその価値があります)で簡単にダウンロードできます。


2

関数の/クラスは、そのオブジェクトスコープに対して単一のコンストラクターのみを許可します。 Function Hoisting, declarations & expressions

  • Functionコンストラクターで作成された関数は、作成コンテキストにクロージャーを作成しません。それらは常にグローバルスコープで作成されます。

      var functionClass = function ( ) {
            var currentClass = Shape;
            _inherits(currentClass, superClass);
            function functionClass() { superClass.call(this); // Linking with SuperClass Constructor.
                // Instance Variables list.
                this.id = id;   return this;
            }
        }(SuperClass)

クロージャ -クロージャのコピーは、データが保持された機能です。

  • 各クロージャーのコピーは、独自の空き値または参照を持つ関数に作成されます。別の関数内で関数を使用する場合は常に、クロージャーが使用されます。
  • JavaScriptでのクロージャーは、innerFunctionsによって親関数のすべてのローカル変数のコピーを維持するようなものです。

      function closureFun( args ) {
            // Local variable that ends up within closure
            var num = args;
            num++;
            return function() { console.log(num); }
        }
        var closure1 = closureFun( 5 );
        var closure2 = closureFun( 777 );
        closure1(); // 5
        closure2(); // 777
        closure2(); // 778
        closure1(); // 6

ES5関数クラスObject.defineProperty(O、P、属性)を使用します

Object.defineProperty()メソッドは、オブジェクトに直接新しいプロパティを定義し、またはオブジェクト上の既存のプロパティを変更し、オブジェクトを返します。

``を使用していくつかのメソッドを作成し、関数クラスを簡単に理解できるようにしました。

'use strict';
var Shape = function ( superClass ) {
    var currentClass = Shape;
    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Shape(id) { superClass.call(this); // Linking with SuperClass Constructor.
        // Instance Variables list.
        this.id = id;   return this;
    }
    var staticVariablesJOSN = { "parent_S_V" : 777 };
    staticVariable( currentClass, staticVariablesJOSN );

    // Setters, Getters, instanceMethods. [{}, {}];
    var instanceFunctions = [
        {
            key: 'uniqueID',
            get: function get() { return this.id; },
            set: function set(changeVal) { this.id = changeVal; }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Object);

var Rectangle = function ( superClass ) {
    var currentClass = Rectangle;

    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Rectangle(id, width, height) { superClass.call(this, id); // Linking with SuperClass Constructor.

        this.width = width;
        this.height = height;   return this;
    }

    var staticVariablesJOSN = { "_staticVar" : 77777 };
    staticVariable( currentClass, staticVariablesJOSN );

    var staticFunctions = [
        {
            key: 'println',
            value: function println() { console.log('Static Method'); }
        }
    ];
    staticMethods(currentClass, staticFunctions);

    var instanceFunctions = [
        {
            key: 'setStaticVar',
            value: function setStaticVar(staticVal) {
                currentClass.parent_S_V = staticVal;
                console.log('SET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
            }
        }, {
            key: 'getStaticVar',
            value: function getStaticVar() {
                console.log('GET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
                return currentClass.parent_S_V;
            }
        }, {
            key: 'area',
            get: function get() {
                console.log('Area : ', this.width * this.height);
                return this.width * this.height;
                }
        }, {
            key: 'globalValue',
            get: function get() {
                console.log('GET ID : ', currentClass._staticVar);
                return currentClass._staticVar;
            },
            set: function set(value) {
                currentClass._staticVar = value;
                console.log('SET ID : ', currentClass._staticVar);
            }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Shape);

// ===== ES5 Class Conversion Supported Functions =====
function defineProperties(target, props) {
    console.log(target, ' : ', props);
    for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
    }
}
function staticMethods( currentClass, staticProps ) {
    defineProperties(currentClass, staticProps);
};
function instanceMethods( currentClass, protoProps ) {
    defineProperties(currentClass.prototype, protoProps);
};
function staticVariable( currentClass, staticVariales ) {
    // Get Key Set and get its corresponding value.
    // currentClass.key = value;
    for( var prop in staticVariales ) {
        console.log('Keys : Values');
        if( staticVariales.hasOwnProperty( prop ) ) {
            console.log(prop, ' : ', staticVariales[ prop ] );
            currentClass[ prop ] = staticVariales[ prop ];
        }
    }
};
function _inherits(subClass, superClass) {
    console.log( subClass, ' : extends : ', superClass );
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, 
            { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });
    if (superClass)
        Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

以下のコードスニペットは、各インスタンスがインスタンスメンバーと共通の静的メンバーの独自のコピーを持つかどうかをテストするためのものです。

var objTest = new Rectangle('Yash_777', 8, 7);
console.dir(objTest);

var obj1 = new Rectangle('R_1', 50, 20);
Rectangle.println(); // Static Method
console.log( obj1 );    // Rectangle {id: "R_1", width: 50, height: 20}
obj1.area;              // Area :  1000
obj1.globalValue;       // GET ID :  77777
obj1.globalValue = 88;  // SET ID :  88
obj1.globalValue;       // GET ID :  88  

var obj2 = new Rectangle('R_2', 5, 70);
console.log( obj2 );    // Rectangle {id: "R_2", width: 5, height: 70}
obj2.area;              // Area :  350    
obj2.globalValue;       // GET ID :  88
obj2.globalValue = 999; // SET ID :  999
obj2.globalValue;       // GET ID :  999

console.log('Static Variable Actions.');
obj1.globalValue;        // GET ID :  999

console.log('Parent Class Static variables');
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  777
obj1.setStaticVar(7);   // SET Instance Method Parent Class Static Value :  7
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  7

静的メソッドの呼び出しはクラスで直接行われ、クラスのインスタンスでは呼び出すことができません。ただし、インスタンス内から静的メンバーの呼び出しを実行できます。

構文を使用:

   this.constructor.staticfunctionName();
class MyClass {
    constructor() {}
    static staticMethod() {
        console.log('Static Method');
    }
}
MyClass.staticVar = 777;

var myInstance = new MyClass();
// calling from instance
myInstance.constructor.staticMethod();
console.log('From Inside Class : ',myInstance.constructor.staticVar);

// calling from class
MyClass.staticMethod();
console.log('Class : ', MyClass.staticVar);

ES6クラス:ES2015クラスは、プロトタイプベースのOOパターンに対する単純な砂糖です。単一の便利な宣言型フォームを使用すると、クラスパターンが使いやすくなり、相互運用性が向上します。クラスは、プロトタイプベースの継承、スーパーコール、インスタンスおよび静的メソッドとコンストラクタをサポートします。

:以前の投稿を参照してください。


2

JavaScriptで関数ローカルの静的変数をエミュレートするには、4つの方法があります。

方法1:関数オブジェクトのプロパティを使用する(古いブラウザーでサポートされていました)

function someFunc1(){
    if( !('staticVar' in someFunc1) )
        someFunc1.staticVar = 0 ;
    alert(++someFunc1.staticVar) ;
}

someFunc1() ; //prints 1
someFunc1() ; //prints 2
someFunc1() ; //prints 3

方法2:クロージャーを使用する、バリアント1(古いブラウザーでサポート)

var someFunc2 = (function(){
    var staticVar = 0 ;
    return function(){
        alert(++staticVar) ;
    }
})()

someFunc2() ; //prints 1
someFunc2() ; //prints 2
someFunc2() ; //prints 3

方法3:クロージャーのバリアント2を使用(古いブラウザーでもサポート)

var someFunc3 ;
with({staticVar:0})
    var someFunc3 = function(){
        alert(++staticVar) ;
    }

someFunc3() ; //prints 1
someFunc3() ; //prints 2
someFunc3() ; //prints 3

方法4:クロージャーを使用する、バリアント3(EcmaScript 2015のサポートが必要)

{
    let staticVar = 0 ;
    function someFunc4(){
        alert(++staticVar) ;
    }
}

someFunc4() ; //prints 1
someFunc4() ; //prints 2
someFunc4() ; //prints 3

2

次のキーワードを使用して、JavaScriptで静的関数を定義できますstatic

class MyClass {
  static myStaticFunction() {
    return 42;
  }
}

MyClass.myStaticFunction(); // 42

この記事を書いている時点では、クラス内で(関数以外の)静的プロパティを定義することはできません。静的プロパティはまだステージ3の提案です。つまり、静的プロパティはまだJavaScriptの一部ではありません。ただし、他のオブジェクトと同じように、単にクラスに割り当てることを妨げるものは何もありません。

class MyClass {}

MyClass.myStaticProperty = 42;

MyClass.myStaticProperty; // 42

最後の注意:継承を伴う静的オブジェクトの使用には注意してください。継承されたすべてのクラスは、オブジェクトの同じコピーを共有します


1

JavaScriptには静的な用語やキーワードはありませんが、そのようなデータを(他のオブジェクトと同様に)関数オブジェクトに直接入れることができます。

function f() {
    f.count = ++f.count || 1 // f.count is undefined at first
    alert("Call No " + f.count)
}

f(); // Call No 1

f(); // Call No 2

1

私は静的関数変数を頻繁に使用していますが、これはJSにそのための組み込みメカニズムがないのは残念です。変数と関数が1つの関数内で使用されているだけでも、外部スコープで定義されているコードを頻繁に目にします。これは醜く、エラーが発生しやすく、問題を尋ねるだけです...

私は次の方法を思いつきました:

if (typeof Function.prototype.statics === 'undefined') {
  Function.prototype.statics = function(init) {
    if (!this._statics) this._statics = init ? init() : {};
    return this._statics;
  }
}

これは、すべての関数に「静的」メソッドを追加します(そう、それについてリラックスするだけです)。呼び出されると、関数オブジェクトに空のオブジェクト(_statics)が追加され、それが返されます。init関数が指定されている場合、_staticsはinit()の結果に設定されます。

その後、次のことができます。

function f() {
  const _s = f.statics(() => ({ v1=3, v2=somefunc() });

  if (_s.v1==3) { ++_s.v1; _s.v2(_s.v1); }
} 

これを他の正解であるIIFEと比較すると、これには、関数呼び出しごとに1つの代入と1つの代入を追加し、関数に「_statics」メンバーを追加するという欠点がありますが、いくつかの利点があります。引数は内部関数コードでは 'static'を使用しているため、内部関数にないトップは '_s'で明示されます。接頭辞、そしてそれを見て理解することは全体的に簡単です。


1

概要:

ではES6/ ES 2015 classキーワードが伴って導入されたstaticキーワード。これは、javavscriptが具現化するプロトタイプの継承モデルに対する構文上の砂糖であることを覚えておいてください。staticキーワードは、方法については、以下のように動作します。

class Dog {

  static bark () {console.log('woof');}
  // classes are function objects under the hood
  // bark method is located on the Dog function object
  
  makeSound () { console.log('bark'); }
  // makeSound is located on the Dog.prototype object

}

// to create static variables just create a property on the prototype of the class
Dog.prototype.breed = 'Pitbull';
// So to define a static property we don't need the `static` keyword.

const fluffy = new Dog();
const vicky = new Dog();
console.log(fluffy.breed, vicky.breed);

// changing the static variable changes it on all the objects
Dog.prototype.breed = 'Terrier';
console.log(fluffy.breed, vicky.breed);


2
彼は静的関数ではなく、静的変数を求めていました。
KonradHöffner2018

1

私はプロトタイプを使用し、そのように機能しました:

class Cat extends Anima {
  constructor() {
    super(Cat.COLLECTION_NAME);
  }
}

Cat.COLLECTION_NAME = "cats";

または静的ゲッターを使用します:

class Cat extends Anima {
  constructor() {
    super(Cat.COLLECTION_NAME);
  }

  static get COLLECTION_NAME() {
    return "cats"
  }
}

0

ウィンドウレベルの変数は、直接参照を使用でき、これらはアプリのすべての部分で使用できるという意味で、静的のようなものです


3
そのような変数のより良い説明は、静的ではなく「グローバル」です。
Patrick M

0

Javascriptには静的変数などはありません。この言語はプロトタイプベースのオブジェクト指向であるため、クラスはありませんが、オブジェクトが自分自身を「コピー」する場所からのプロトタイプがあります。

グローバル変数またはプロトタイピング(プロトタイプにプロパティを追加)でそれらをシミュレートできます。

function circle(){
}
circle.prototype.pi=3.14159

この方法は機能しますが、汚染されていますFunction.prototype
Dan

@ダン:これは円ではなく機能ではないというのが私の理解です。少なくともそれはChromeが私に伝えようとしていることです: function circle() {}| circle.prototype| circle.prototype.pi = 3.14| circle.prototype| Function.prototype| Function.__proto__(それがあなたが意図したものである場合)
Aktau 2013年

0

jQueryを使用するMVC Webサイトを使用して、特定のイベントハンドラー内のAJAXアクションが、前のリクエストが完了した後にのみ実行できることを確認したいです。これを実現するには、「静的」jqXHRオブジェクト変数を使用します。

次のボタンがあるとします:

<button type="button" onclick="ajaxAction(this, { url: '/SomeController/SomeAction' })">Action!</button>

私は通常、クリックハンドラーに次のようなIIFEを使用します。

var ajaxAction = (function (jqXHR) {
    return function (sender, args) {
        if (!jqXHR || jqXHR.readyState == 0 || jqXHR.readyState == 4) {
            jqXHR = $.ajax({
                url: args.url,
                type: 'POST',
                contentType: 'application/json',
                data: JSON.stringify($(sender).closest('form').serialize()),
                success: function (data) {
                    // Do something here with the data.
                }
            });
        }
    };
})(null);

0

プロトタイプを使用したい場合は、方法があります

var p = function Person() {
    this.x = 10;
    this.y = 20;
}
p.prototype.counter = 0;
var person1 = new p();
person1.prototype = p.prototype;
console.log(person1.counter);
person1.prototype.counter++;
var person2 = new p();
person2.prototype = p.prototype;
console.log(person2.counter);
console.log(person1.counter);

これを行うと、任意のインスタンスからカウンター変数にアクセスでき、プロパティの変更がすぐに反映されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.