私はゲッターとセッターの周りに頭を近づけようとしましたが、沈みません。JavaScriptのゲッターとセッター、およびゲッターとセッターの定義を読んだだけで、理解できません。
誰かが明確に述べることができます:
- ゲッターとセッターが何をするためのものか、そして
- 非常に簡単な例を挙げてください。
a = setValue(5);
とa = 5;
し、setValue()
それによって、あなたが好きなものは何でもするためにボンネットの下に呼び出されます。
私はゲッターとセッターの周りに頭を近づけようとしましたが、沈みません。JavaScriptのゲッターとセッター、およびゲッターとセッターの定義を読んだだけで、理解できません。
誰かが明確に述べることができます:
a = setValue(5);
とa = 5;
し、setValue()
それによって、あなたが好きなものは何でもするためにボンネットの下に呼び出されます。
回答:
@millimooseの回答に加えて、セッターを使用して他の値を更新することもできます。
function Name(first, last) {
this.first = first;
this.last = last;
}
Name.prototype = {
get fullName() {
return this.first + " " + this.last;
},
set fullName(name) {
var names = name.split(" ");
this.first = names[0];
this.last = names[1];
}
};
さて、あなたは設定することができfullName
、かつfirst
およびlast
更新され、その逆されます。
n = new Name('Claude', 'Monet')
n.first # "Claude"
n.last # "Monet"
n.fullName # "Claude Monet"
n.fullName = "Gustav Klimt"
n.first # "Gustav"
n.last # "Klimt"
Object.defineProperty
ゲッターとセッターを定義できる新しい関数をサポートしています。
this.__defineGetter__
またはより新しいObject.defineProperty
関数を使用する必要があります。
Name.prototype.constructor
か?millimooseのAnswerの悪い代替案のようです。
JavaScriptのゲッターとセッターは、計算されたプロパティまたはアクセサーの定義に使用されます。計算されたプロパティは、関数を使用してオブジェクト値を取得または設定するプロパティです。基本的な理論は次のようなことをしています:
var user = { /* ... object with getters and setters ... */ };
user.phone = '+1 (123) 456-7890'; // updates a database
console.log( user.areaCode ); // displays '123'
console.log( user.area ); // displays 'Anytown, USA'
これは、プロパティへのアクセス時に、数値が範囲内に留まる、文字列を再フォーマットする、値が変更されたイベントをトリガーする、リレーショナルデータを更新する、プライベートプロパティへのアクセスを提供するなど、舞台裏で自動的に行うのに役立ちます。
以下の例は基本的な構文を示していますが、特別なことをせずに内部オブジェクト値を取得および設定するだけです。上記のように、実際のケースでは、必要に応じて入力値または出力値、あるいはその両方を変更します。
ECMAScript 5はget
、set
計算されたプロパティを定義するためのとキーワードをサポートしています。IE 8以下を除くすべての最新ブラウザーで動作します。
var foo = {
bar : 123,
get bar(){ return bar; },
set bar( value ){ this.bar = value; }
};
foo.bar = 456;
var gaz = foo.bar;
get
およびset
は予約語ではないため、オーバーロードして独自のカスタムブラウザー間計算プロパティ関数を作成できます。これはどのブラウザでも機能します。
var foo = {
_bar : 123,
get : function( name ){ return this[ '_' + name ]; },
set : function( name, value ){ this[ '_' + name ] = value; }
};
foo.set( 'bar', 456 );
var gaz = foo.get( 'bar' );
または、よりコンパクトなアプローチでは、単一の関数を使用できます。
var foo = {
_bar : 123,
value : function( name /*, value */ ){
if( arguments.length < 2 ){ return this[ '_' + name ]; }
this[ '_' + name ] = value;
}
};
foo.value( 'bar', 456 );
var gaz = foo.value( 'bar' );
このようなことはコードの肥大化につながる可能性があるため、避けてください。
var foo = {
_a : 123, _b : 456, _c : 789,
getA : function(){ return this._a; },
getB : ..., getC : ..., setA : ..., setB : ..., setC : ...
};
上記の例については、内部プロパティ名は、単にやってからユーザーを阻止するために、アンダースコアで抽象化されているfoo.bar
対をfoo.get( 'bar' )
して「生」の値を取得します。条件付きコードを使用して、(name
パラメーターを介して)アクセスされているプロパティの名前に応じてさまざまなことを実行できます。
使用Object.defineProperty()
はゲッターとセッターを追加するもう1つの方法であり、定義後にオブジェクトで使用できます。また、構成可能で列挙可能な動作を設定するためにも使用できます。この構文はIE 8でも機能しますが、残念ながらDOMオブジェクトでのみ機能します。
var foo = { _bar : 123 };
Object.defineProperty( foo, 'bar', {
get : function(){ return this._bar; },
set : function( value ){ this._bar = value; }
} );
foo.bar = 456;
var gaz = foo.bar;
最後に、__defineGetter__()
別のオプションです。これは非推奨ですが、Webで広く使用されているため、すぐになくなることはほとんどありません。IE 10以下を除くすべてのブラウザで動作します。他のオプションもIE以外でうまく機能するので、これはそれほど有用ではありません。
var foo = { _bar : 123; }
foo.__defineGetter__( 'bar', function(){ return this._bar; } );
foo.__defineSetter__( 'bar', function( value ){ this._bar = value; } );
また、注目に値する後者の例では、内部名は(すなわち、回避再帰へのアクセサ名とは異なるなければならないことであるfoo.bar
呼び出すfoo.get(bar)
呼び出しfoo.bar
を呼び出しますfoo.get(bar)
...)。
MDN get、set、
Object.defineProperty()、__ defineGetter __()、__ defineSetter __()
MSDN
IE8 Getter Support
this[ '_' + name ] = value;
かもしれないthis[ '_' + name ] = arguments[1];
と指定する必要はないだろうvalue
argが。
var foo = { bar : 123, get bar(){ return bar; }, set bar( value ){ this.bar = value; } }; foo.bar = 456;
例外を発生させます:Uncaught RangeError:最大コールスタックサイズがObject.setバーで[バーとして](<anonymous>:4:32)Object.setバーで[バーとして](<anonymous>:4:32) )at Object.set bar [as bar](<anonymous>:4:32)at Object.set bar [as bar](<anonymous>:4:32)at Object.set bar [as bar](<anonymous> :4:32)at Object.set bar [as bar](<anonymous>:4:32)
bar: 123
、this.bar = value
などをこれらに変更してください_bar
。参照:hongkiat.com/blog/getters-setters-javascript
_foo
かmFoo
。ゲッター/セッターと同じ場合、再帰による無限ループが発生し、次にStack Overflow™;-)が発生します。 、これはa.get(b)を呼び出します...
たとえば、これらを使用して、計算されたプロパティを実装します。
例えば:
function Circle(radius) {
this.radius = radius;
}
Object.defineProperty(Circle.prototype, 'circumference', {
get: function() { return 2*Math.PI*this.radius; }
});
Object.defineProperty(Circle.prototype, 'area', {
get: function() { return Math.PI*this.radius*this.radius; }
});
c = new Circle(10);
console.log(c.area); // Should output 314.159
console.log(c.circumference); // Should output 62.832
Object.defineProperties
。
古い質問を復活させて申し訳ありませんが、私はいくつかの非常に基本的な例と一般向けの説明を提供すると思います。これまでに投稿された他の回答はどれも、MDNガイドの最初の例のような構文を示していません。
ゲッター:
var settings = {
firstname: 'John',
lastname: 'Smith',
get fullname() { return this.firstname + ' ' + this.lastname; }
};
console.log(settings.fullname);
...はJohn Smith
もちろん記録されます。ゲッター変数オブジェクトのプロパティのように動作しますが、その場でその戻り値を計算する機能の柔軟性を提供します。これは基本的に、呼び出し時に()を必要としない関数を作成するための洗練された方法です。
セッター:
var address = {
set raw(what) {
var loc = what.split(/\s*;\s*/),
area = loc[1].split(/,?\s+(\w{2})\s+(?=\d{5})/);
this.street = loc[0];
this.city = area[0];
this.state = area[1];
this.zip = area[2];
}
};
address.raw = '123 Lexington Ave; New York NY 10001';
console.log(address.city);
... New York
コンソールに記録します。getterと同様に、setterはオブジェクトプロパティの値を設定するのと同じ構文で呼び出されますが、()なしで関数を呼び出すもう1つの豪華な方法です。
より徹底的で、おそらくより実用的な例については、このjsfiddleを参照してください。オブジェクトのセッターに値を渡すと、他のオブジェクトアイテムの作成または生成がトリガーされます。具体的には、jsfiddleの例では、数値の配列を渡すと、セッターが平均値、中央値、モード、および範囲を計算するように求められます。次に、各結果のオブジェクトプロパティを設定します。
maps.roll
は、maps.roll()
戻り値ではなくプロパティとして取得することが役に立ちました。それは単なる好みです。
maps.roll()
ゲッターとセッターは、クラスのプライベートプロパティがある場合にのみ意味があります。Javascriptには、通常オブジェクト指向言語で考えるようなプライベートクラスプロパティがないため、理解しにくい場合があります。次に、プライベートカウンターオブジェクトの例を示します。このオブジェクトの良い点は、内部変数「count」にオブジェクトの外部からアクセスできないことです。
var counter = function() {
var count = 0;
this.inc = function() {
count++;
};
this.getCount = function() {
return count;
};
};
var i = new Counter();
i.inc();
i.inc();
// writes "2" to the document
document.write( i.getCount());
それでも混乱している場合は、JavaScriptのプライベートメンバーに関するクロックフォードの記事をご覧ください。
var baz = foo.bar
その背後に隠された振る舞いの完全なセットがあるとは絶対に期待しません。しかし、私はそれを期待していfoo.getBar()
ます。
あなたがリンクする最初の記事はそれをかなり明確に述べていると思います:
この方法でJavaScriptを記述することの明らかな利点は、ユーザーが直接アクセスすることを望まないあいまいな値を使用できることです。
ここでの目標は、get()
またはset()
メソッドを介してフィールドへのアクセスのみを許可することにより、フィールドをカプセル化して抽象化することです。このようにして、フィールド/データを任意の方法で内部に格納できますが、外部コンポーネントは公開されたインターフェースから離れているだけです。これにより、外部インターフェイスを変更せずに内部の変更を加えたり、set()
メソッド内で検証やエラーチェックを行ったりできます。
アクセス制御のないパブリックプロパティを持つオブジェクトの表示に慣れていることがよくありますが、JavaScriptを使用すると、プロパティを正確に記述することができます。実際、プロパティへのアクセス方法とそれに適用できるロジックを制御するために、記述子を使用できます。次の例について考えてみます。
var employee = {
first: "Boris",
last: "Sergeev",
get fullName() {
return this.first + " " + this.last;
},
set fullName(value) {
var parts = value.toString().split(" ");
this.first = parts[0] || "";
this.last = parts[1] || "";
},
email: "boris.sergeev@example.com"
};
最終結果:
console.log(employee.fullName); //Boris Sergeev
employee.fullName = "Alex Makarenko";
console.log(employee.first);//Alex
console.log(employee.last);//Makarenko
console.log(employee.fullName);//Alex Makarenko
何がそんなに紛らわしいのですか?getterは、プロパティを取得するときに呼び出される関数であり、設定するときに設定します。たとえば、
obj.prop = "abc";
プロパティプロップを設定しています。ゲッター/セッターを使用している場合は、「abc」を引数として、セッター関数が呼び出されます。オブジェクト内のセッター関数の定義は、理想的には次のようになります。
set prop(var) {
// do stuff with var...
}
それがどのようにブラウザ全体に実装されているのかはわかりません。Firefoxにも、二重下線付きの特別な(「マジック」)メソッドを使用した代替構文があるようです。いつものように、Internet Explorerはこれをサポートしていません。
コンストラクタのプロトタイプを介して、jsクラスのインスタンスメソッドを定義できます。
次にサンプルコードを示します。
// BaseClass
var BaseClass = function(name) {
// instance property
this.name = name;
};
// instance method
BaseClass.prototype.getName = function() {
return this.name;
};
BaseClass.prototype.setName = function(name) {
return this.name = name;
};
// test - start
function test() {
var b1 = new BaseClass("b1");
var b2 = new BaseClass("b2");
console.log(b1.getName());
console.log(b2.getName());
b1.setName("b1_new");
console.log(b1.getName());
console.log(b2.getName());
}
test();
// test - end
そして、これはどのブラウザでも動作するはずです。nodejsを使用してこのコードを実行することもできます。
アクセサーの概念を参照している場合、単純な目標は、基礎となるストレージを任意の操作から隠すことです。このための最も極端なメカニズムは
function Foo(someValue) {
this.getValue = function() { return someValue; }
return this;
}
var myFoo = new Foo(5);
/* We can read someValue through getValue(), but there is no mechanism
* to modify it -- hurrah, we have achieved encapsulation!
*/
myFoo.getValue();
たとえば、実際のJSゲッター/セッター機能を参照している場合。defineGetter
/ defineSetter
、または{ get Foo() { /* code */ } }
、それから、ほとんどの最新のエンジンでは、それらのプロパティのその後の使用は、それ以外の場合よりもはるかに遅くなることに注意する価値があります。例えば。のパフォーマンスを比較する
var a = { getValue: function(){ return 5; }; }
for (var i = 0; i < 100000; i++)
a.getValue();
対
var a = { get value(){ return 5; }; }
for (var i = 0; i < 100000; i++)
a.value;
少し醜いかもしれませんが、プラットフォーム間でうまくいきます。
function myFunc () {
var _myAttribute = "default";
this.myAttribute = function() {
if (arguments.length > 0) _myAttribute = arguments[0];
return _myAttribute;
}
}
このように、あなたが呼び出すとき
var test = new myFunc();
test.myAttribute(); //-> "default"
test.myAttribute("ok"); //-> "ok"
test.myAttribute(); //-> "ok"
あなたが本当に物事にスパイスをかけたいなら、あなたはtypeofチェックを挿入することができます:
if (arguments.length > 0 && typeof arguments[0] == "boolean") _myAttribute = arguments[0];
if (arguments.length > 0 && typeof arguments[0] == "number") _myAttribute = arguments[0];
if (arguments.length > 0 && typeof arguments[0] == "string") _myAttribute = arguments[0];
または、高度なtypeofチェックでさらにクレイジーになります:codingforums.comのtype.of()コード