Javascriptで静的変数を作成する方法
クラスベースの静的型付けオブジェクト指向言語 (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();
staticProperty
はMyClassオブジェクト(関数)で定義されており、作成されたインスタンスとは無関係です。JavaScriptは関数を ファーストクラスオブジェクト として扱うため、オブジェクトであるため、プロパティを関数に割り当てることができます。
あなたは、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.
これは、あなたに同じ種類の結果をもたらします - ただし、今回は、表示されずに増分値が返されます。
これはIIFE(すぐに呼び出される関数式)を通して行います。
var incr = (function () {
var i = 1;
return function () {
return i++;
}
})();
incr(); // returns 1
incr(); // returns 2
"静的な"変数を格納するためにarguments.calleeを使うことができます(これは無名関数でも役に立ちます)。
function () {
arguments.callee.myStaticVar = arguments.callee.myStaticVar || 1;
arguments.callee.myStaticVar++;
alert(arguments.callee.myStaticVar);
}
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();
同様の回答をいくつか見ましたが、 この投稿 が最もよく説明していることを述べたいと思いますので、あなたと共有したいと思います。
以下にいくつかのコードを示します。これは、クラスのデザインテンプレートとして使用できるため、コミュニティに利益をもたらす可能性のある完全な例を得るために修正しました。
質問に答える
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 + ' ...');
};
その例を考えると、次のようにstatic properties/functionにアクセスできます。
// access static properties/functions
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()にはclosure :があります。_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) }
});
get
およびset
関数を介してプロパティd.year
を定義します-set
を指定しない場合、プロパティは読み取り専用であり、変更できません(注意してください)設定しようとしてもエラーは発生しませんが、効果はありません)。各プロパティには、writable
、configurable
(宣言後に変更を許可)、およびenumerable
(列挙子として使用を許可)の属性があり、デフォルトではfalse
です。 3番目のパラメーターのdefineProperty
を介して設定できます。 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章(オブジェクト)でさらに説明します。
a
とb
はPodcast
から継承すると言うことができます。では、a
とb
がインスタンス化された後、それらすべてに適用されるメソッドをPodcastに追加したい場合はどうでしょうか。この場合、次のように.prototype
を使用します。
Podcast.prototype.titleAndLink = function() {
return this.title + " [" + this.link + "]";
};
a
とb
をもう一度呼び出します:
console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
プロトタイプの詳細については、 here を参照してください。さらに継承したい場合は、 this を調べることをお勧めします。
上記の 記事シリーズ は強くお勧めしますを読むことです。以下のトピックも含まれています。
注 JavaScriptの(6.で述べたように)自動セミコロン挿入「機能」コードに奇妙な問題を引き起こす原因となります。したがって、私はむしろそれを機能としてではなくバグと見なします。
さらに詳しく知りたい場合は、 here は非常に興味深いMSDN記事で、ここで説明されているトピックのいくつかはさらに詳細を提供します。
おもしろい(上記のトピックもカバーしています)は、 MDN JavaScriptガイド の記事です。
JavaScriptでc#out
parameters(DateTime.TryParse(str, out result)
のように)をエミュレートする方法を知りたい場合は、sample codeを参照してください。
IEでの作業(を使用して開発者ツールを開かない限り、JavaScriptのコンソールはありません。F12でコンソールタブを開きます)、次のスニペットが役立つ場合があります。上記の例で使用されているconsole.log(msg);
を使用できます。 Podcast
関数の前に挿入してください。
便宜上、上記のコードを1つの完全なコードスニペットに示します。
let console = { log: function(msg) {
let canvas = document.getElementById("log"), br = canvas.innerHTML==="" ? "" : "<br/>";
canvas.innerHTML += (br + (msg || "").toString());
}};
console.log('For details, see the explaining text');
function Podcast() {
// with this, you can instantiate without new (see description in text)
if (false === (this instanceof Podcast)) {
return new Podcast();
}
// private variables
var _somePrivateVariable = 123;
// object properties
this.title = 'Astronomy Cast';
this.description = 'A fact-based journey through the galaxy.';
this.link = 'http://www.astronomycast.com';
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
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
// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
get: function() {
return this.getFullYear()
},
set: function(y) {
this.setFullYear(y)
}
});
// getters and setters - alternative syntax
var obj = {
a: 7,
get b() {
return this.a + 1;
},
set c(x) {
this.a = x / 2
}
};
// usage:
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
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"
Podcast.prototype.titleAndLink = function() {
return this.title + " [" + this.link + "]";
};
console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
<div id="log"></div>
注:
JavaScriptプログラミングに関する一般的なヒント、ヒント、推奨事項は、here(JavaScriptベストプラクティス)およびthere( 「var」対「let」)。また、この記事暗黙的な型キャスト(強制)についてもお勧めします。
クラスを使用してJavaScriptにコンパイルする便利な方法はTypeScript。ここに遊び場があります です。使い方。現時点でTypeScriptを使用していない場合でも、TypeScriptとJavaScriptの結果を並べて表示することができるため、外観を確認できます。ほとんどの例は単純ですが、すぐに試用できるレイトレーサーの例もあります。特に、「クラスの使用」、「継承の使用」、「ジェネリックの使用」の例をコンボボックスで選択して調べることをお勧めします。これらはJavaScriptですぐに使用できる素敵なテンプレートです。 TypeScriptは Angular。 で使用されます
JavaScriptでローカル変数、関数などのencapsulationを実現するには、次のようなパターンを使用することをお勧めします(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: </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
ファイルに入れることができます-すべきです-これは、例を短くするためにインラインで記述されています。
更新された答え:
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
JavaScriptでは関数はオブジェクトなので、Foo
のプロパティに代入できます。
次の例と説明は、Nicholas Zakasによる「Web開発者のためのプロフェッショナルJavaScript第2版」からのものです。これが私が探していた答えなので、それをここに追加すると便利だと思いました。
(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変数は静的になり、すべてのインスタンスで使用されます。つまり、1つのインスタンスでsetName()
を呼び出すと、他のすべてのインスタンスに影響があります。 setName()
を呼び出すか、または新しいPerson
インスタンスを作成すると、name変数に新しい値が設定されます。これにより、すべてのインスタンスが同じ値を返します。
新しい クラス構文 を使用している場合は、次の操作を実行できます。
class MyClass {
static get myStaticVariable() {
return "some static variable";
}
}
console.log(MyClass.myStaticVariable);
aMyClass = new MyClass();
console.log(aMyClass.myStaticVariable, "is undefined");
これにより、JavaScriptでは事実上静的変数が作成されます。
あなたのアプリケーションで定数を作成するために静的変数を宣言したいのであれば、私は最も単純化されたアプローチとして以下のことを発見しました。
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;
ECMAScript 2015で紹介された class
について。他の答えは完全には明らかではありません。
これはstaticVar
.ClassName
シンタクスを使って静的変数var
を作成する方法を示す例です。
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
他にも似たような答えがありますが、どれも私に訴えかけませんでした。これが私が最後になったものです:
var nextCounter = (function () {
var counter = 0;
return function() {
var temp = counter;
counter += 1;
return temp;
};
})();
以下のように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
グローバル静的変数を作りたい場合は、
var my_id = 123;
変数を以下で置き換えます。
Object.defineProperty(window, 'my_id', {
get: function() {
return 123;
},
configurable : false,
enumerable : false
});
JavaScriptでは、変数はデフォルトで static です。 例 :
var x = 0;
function draw() {
alert(x); //
x+=1;
}
setInterval(draw, 1000);
Xの値は1000ミリ秒ごとに1ずつ増加します
1,2,3などと表示されます
ここですべてのクラス概念を要約するには、これをテストしてください。
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
さて、これらのことのベストプラクティスに目を向けるもう一つの方法は、コーヒースクリプトがこれらの概念をどのように翻訳するかを見ることです。
#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);
このスレッドを閲覧した後に私の要件を解決した別のアプローチがあります。それはあなたが「静的変数」で何を達成したいのかに正確に依存します。
グローバルプロパティ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購読(金でその価値がある)で簡単にダウンロードできます。
JavaScriptで静的変数に最も近いものはグローバル変数です。これは単に関数またはオブジェクトリテラルの範囲外で宣言された変数です。
var thisIsGlobal = 1;
function foo() {
var thisIsNot = 2;
}
他にできることは、グローバル変数を次のようなオブジェクトリテラル内に格納することです。
var foo = { bar : 1 }
そして、foo.bar
のようにバリアラベルにアクセスします。
その他に加えて、現在、 ECMA Proposals にドラフト( ステージ2の提案 )があり、クラス内にstatic
public フィールドを導入しています。 ( プライベートフィールドが考慮されました )
提案の例を使用すると、提案されたstatic
構文は次のようになります。
class CustomDate {
// ...
static Epoch = new CustomDate(0);
}
そして他の人が強調している次のものと同等である:
class CustomDate {
// ...
}
CustomDate.Epoch = new CustomDate(0);
それからCustomDate.Epoch
を通してそれにアクセスすることができます。
proposal-static-class-features
で新しいプロポーザルを追跡できます。
現在、babelは トランスフォームクラスのプロパティ pluginを使ってこの機能をサポートしています。さらに、まだ進行中ですが、 V8
がそれを実装しています 。
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
}
クロムのdevtoolsでは、これをうまく視覚化できます。
ClassName.method()
を介して実行できるstatic
関数を作成しました
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
関数の/クラスは、そのオブジェクトスコープに対して単一のコンストラクタのみを許可します。 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)
クロージャ - クロージャのコピーは保存されたデータで機能します。
- 各クロージャのコピーは、それぞれ独自の自由な値または参照を使用して関数に作成されます。別の関数内でfunctionを使用すると、クロージャが使用されます。
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関数クラス :uses Object.defineProperty(O、P、Attributes)
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パターンを超える単純な糖です。便利な宣言形式を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
プロトタイプを使用したい場合は方法があります
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);
こうすることで、どのインスタンスからもcounter変数にアクセスでき、プロパティの変更はすぐに反映されます。
これを試してください。
プロパティを定義し、その機能オブジェクトのプロパティを使用するようにそのゲッターとセッターをオーバーライドすると、理論的にはJavaScriptで静的変数を持つことができます。
例えば:
function Animal() {
if (isNaN(this.totalAnimalCount)) {
this.totalAnimalCount = 0;
}
this.totalAnimalCount++;
};
Object.defineProperty(Animal.prototype, 'totalAnimalCount', {
get: function() {
return Animal['totalAnimalCount'];
},
set: function(val) {
Animal['totalAnimalCount'] = val;
}
});
var cat = new Animal();
console.log(cat.totalAnimalCount); //Will produce 1
var dog = new Animal();
console.log(cat.totalAnimalCount); //Will produce 2 and so on.
私は静的関数変数をよく使いますが、JSにはそのためのメカニズムが組み込まれていないのは本当に残念です。変数と関数が1つの関数内で使用されているにもかかわらず、それらが外部スコープで定義されているコードを目にすることはあまりありません。これは醜く、エラーが発生しやすく、単にトラブルを要求しています...
私は以下の方法を思いついた。
if (typeof Function.prototype.statics === 'undefined') {
Function.prototype.statics = function(init) {
if (!this._statics) this._statics = init ? init() : {};
return this._statics;
}
}
これはすべての関数に 'static'メソッドを追加します(そう、単にそれについてリラックスします)。呼び出されると関数オブジェクトに空のオブジェクト(_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つのif文を追加し、関数に '_statics'メンバーを追加するという欠点があります。ただし、いくつかの利点があります。内部関数コードの中で「静的」を使用することは、内部関数の中ではなく、「_ s」で明示的に行われます。接頭辞を付けると、全体的に見て理解しやすくなります。
だから私は他の答えと一緒に見ることはそれらがオブジェクト指向プログラミングにおける静的属性の基本的なアーキテクチャの要求に対処していないということです。
オブジェクト指向プログラミングには、実際には2つの異なるスタイルがあります。1つは「クラスベース」(C++、C#、Javaなど)、もう1つは「プロトタイプ」(Javascript)です。クラスベースの言語では、「静的属性」はインスタンス化されたオブジェクトではなくクラスに関連付けられているはずです。この概念は実際にはJavascriptのようなプロトタイプ言語でははるかに直感的に機能します。これは、親プロトタイプの値として属性を割り当てるだけなのでです。
function MyObject() {};
MyObject.prototype.staticAttribute = "some value";
そして、このようにこのコンストラクタからインスタンス化されたすべてのオブジェクトからそれにアクセスします。
var childObject1 = new MyObject(); // Instantiate a child object
var childObject2 = new MyObject(); // Instantiate another child object
console.log(childObject.staticAttribute); // Access the static Attribute from child 1
console.log(childObject.staticAttribute); // Access the static Attribute from child 2
さて、先に進んでMyObject.prototype.staticAttribute
を変更すると、変更はすぐにそれを継承する子オブジェクトにカスケードされます。
ただし、この属性の「静的」な性質を著しく損なう可能性がある、または単にセキュリティの脆弱性を残す可能性がある「問題点」がいくつかあります。
最初にjQueryのreadyメソッドのような他の関数の中にそれを囲むことによってGlobal名前空間からコンストラクタを隠すことを忘れないでください
$(document).ready(function () {
function MyObject() {
// some constructor instructions
};
MyObject.prototype.staticAttribute = "some value";
var childObject = new MyObject(); // instantiate child object
console.log(childObject.staticAttribute); // test attribute
});
最後に、これを実行しても、属性は自分のスクリプトの他の部分から編集可能であるため、コード内のバグがいずれかの子オブジェクトの属性を上書きして切り離すことがあります。これは親のプロトタイプからのものなので、親の属性を変更しても、子オブジェクトのカスケード属性や静的な属性は変更されません。 こちらのjsfiddleを見てください。 さまざまなシナリオで、子オブジェクトへの変更を停止するためにObject.freeze(obj)
を使用することも、コンストラクタにsetterメソッドとgetterメソッドを設定してクロージャにアクセスすることもできます。
私には、「静的属性」というクラスベースの考え方とこのJavascript実装との間に完全な類似点はないようです。ですから、私はそれがより長期的にはJavascriptにやさしい別のコードパターンを使う方が良いかもしれないと思います。中央のデータストアやキャッシュ、あるいは必要なすべての静的変数を保持するための専用のヘルパーオブジェクトなどです。
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);
私はプロトタイプを使用し、そのように機能しました:
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"
}
}
プライベートスタティック変数の場合、私はこのようにして見つけました:
function Class()
{
}
Class.prototype = new function()
{
_privateStatic = 1;
this.get = function() { return _privateStatic; }
this.inc = function() { _privateStatic++; }
};
var o1 = new Class();
var o2 = new Class();
o1.inc();
console.log(o1.get());
console.log(o2.get()); // 2
ウィンドウレベルの変数は、直接参照を使用できるという意味では静的なようなものであり、これらはアプリケーションのすべての部分で使用できます。
JavaScriptでは、すべてがプリミティブ型かオブジェクトです。関数はオブジェクトです - (キーと値のペア)。
関数を作成すると、2つのオブジェクトが作成されます。関数自体を表すオブジェクトと関数のプロトタイプを表すオブジェクトです。
関数は基本的にその意味でプロパティを持つオブジェクトです。
function name,
arguments length
and the functional prototype.
それで、どこに静的プロパティを設定するべきですか:関数オブジェクトの内側か関数プロトタイプオブジェクトの内側の2つの場所。
これは、new
JavaScriptキーワードを使用して、2つのインスタンスをインスタンス化することを目的としても作成されたスニペットです。
function C () { // function
var privateProperty = "42";
this.publicProperty = "39";
this.privateMethod = function(){
console.log(privateProperty);
};
}
C.prototype.publicMethod = function () {
console.log(this.publicProperty);
};
C.prototype.staticPrototypeProperty = "4";
C.staticProperty = "3";
var i1 = new C(); // instance 1
var i2 = new C(); // instance 2
i1.privateMethod();
i1.publicMethod();
console.log(i1.__proto__.staticPrototypeProperty);
i1.__proto__.staticPrototypeProperty = "2";
console.log(i2.__proto__.staticPrototypeProperty);
console.log(i1.__proto__.constructor.staticProperty);
i1.__proto__.constructor.staticProperty = "9";
console.log(i2.__proto__.constructor.staticProperty);
主な考え方は、インスタンスi1
とi2
が同じ静的プロパティを使用しているということです。
Javascriptには静的変数のようなものはありません。この言語はプロトタイプベースのオブジェクト指向なので、クラスはありませんが、オブジェクトが自分自身を「コピー」する場所からのプロトタイプです。
グローバル変数またはプロトタイピング(プロトタイプにプロパティを追加する)を使用してそれらをシミュレートできます。
function circle(){
}
circle.prototype.pi=3.14159
私はこの考えを答えのどれにも見なかったので、それをリストに追加するだけです。それが重複している場合は私に知らせて私はそれを削除して他の人を支持します。
私は自分のウェブサイトに一種のスーパーグローバルを作成しました。すべてのページをロードするときにロードされるjsファイルがいくつかあり、いくつかのページにしかロードされない他のjsファイルが多数あるため、すべての「グローバル」関数を単一のグローバル変数に入れます。
私が最初にインクルードした "global"ファイルの先頭には宣言があります。
var cgf = {}; // Custom global functions.
それから私はいくつかのグローバルヘルパー関数を愛撫します
cgf.formBehaviors = function()
{
// My form behaviors that get attached in every page load.
}
静的変数が必要な場合は、文書の準備ができている場合やビヘイビアの添付ファイルの外部など、スコープの外側に格納するだけです。 (私はjqueryを使用しますが、それはJavaScriptで動作するはずです)
cgf.first = true;
$.on('click', '.my-button', function()
{
// Don't allow the user to press the submit twice.
if (cgf.first)
{
// first time behavior. such as submit
}
cgf.first = false;
}
もちろんこれはグローバルで静的ではありませんが、ページがロードされるたびに再初期化されるため、同じ目的を達成します。
私は通常 この方法を使用します 2つの主な理由から:
関数のローカル値を保存したい場合は、 "Local.x"、 "Local.y"、 "Local.TempData"などを使用します。
関数の静的な値を保存したい場合は、 "Static.o"、 "Static.Info"、 "Static.count"などを使用します。
[更新2]:同じ方法ですが、IIFEの手法を使用します。
[更新1]:関数用の "静的"および "ローカル"オブジェクトは事前編集スクリプトによって自動的に作成されます!