function
コンストラクターを使用して新しいものを作成する場合Function
、他にアクセスするための非一時的なスコープをどのように指定できますかwindow
(つまり、スコープは、関数が呼び出されるたびではなく、一度だけ評価する必要があります)。目的は、かなりコストのかかる計算を必要とする複数の変数を作成することです。関数が呼び出されるたびにそれらを再作成したくはありませんが、に格納したくありませんwindow
。何か案は?
4 に答える
bind
キーワードを使用して、関数を特定のコンテキストにバインドできます。
var context = {};
var f = new Function("args", "return this").bind(context);
f(); // context
bind は ECMA 5th で定義されているため、すべてのブラウザーに存在するとは限りません。回避策は次のとおりです。
上記の目的のために、静的関数を使用します。これは JavaScript の動作方法であるため、すべての呼び出しでスコープが評価されるのを防ぐことはできませんがwindow
、スコープ チェーンに含めないことで速度を上げることができます。
var namespace = {};
namespace.someMethod = function() {
// do something here.
};
コードのどこからでも、 を使用してそのメソッドを呼び出すことができますnamespace.someMethod();
。ただ気をつけてください。上記は静的メソッドです。インスタンス化せずに呼び出すことができます。ただし、静的関数内で使用してはなりません。this.property
これは、拡張機能にグローバル オブジェクトへのアクセス権と、基本的に無制限のアクセス許可を与える可能性があるため、潜在的に非常に危険な操作です。
上記は静的なJavaScript メソッドです。スコープ チェーンにウィンドウがありません。
同じパターンを使用してコンストラクターを作成する方法を次に示します。コンストラクターを使用する場合は、使用する前に必ずインスタンス化します。そのためにnew
キーワードがあります。
var namespace = {};
namespace.coordinate = function(x, y) {
this.x = x;
this.y = y;
};
namespace.coordinate.prototype.addCoordinates = function() {
return this.x + this.y;
};
コードのどこでもできるようになりました:
var coordinateObject = new namespace.coordinate(5,10);
// you have created a new instance.
alert(coordinateObject.addCoordinates());// will alert 15;
// now you can make as many as you want. They will behave as instances.
// This means they do not interfere with each other in any way.
// They just have the same properties and methods, but the instance values
// Can be entirely different.
var secondCoordinateObject = new namespace.coordinate(10, 25);
alert(secondCoordinateObject.addCoordinates());// will output 35.
クラスのインスタンスが正常に作成されましたnamespace.coordinate
。私が示したパターンを使用すると、Java や C、その他のオブジェクト指向言語のほぼすべての機能を複製できます。
変数と関数を作成、保存、非表示、表示、およびグループ化する方法は、Javascript の最も強力でまだ知られていない機能である「クロージャ」の魔法を使用して、ますます増えています。
var groupObj = (function (setUp) {
// maintained by reference, hidden
var _priVar = setUp * 2;
// maintained by reference, revealed (through returned object)
var _pubVar = 8;
var _pubFunc = function (x) {
_priVar += x;
_pubVar += x;
}
var lostVar = setUp * 99; // not referenced, hidden, so evaporates!
return {
'pubVar' : _pubVar,
'pubFunc' : _pubFunc
}
}(4)); // runs immediately with 4 as setUp, revealing pubVar & pubFunc
それで...
groupObj.pubFunc(7); // runs public function, adds 7 to both variables
alert('public variable: ' + groupObj.pubVar); // alerts public variable
関数が別の関数内にある場合は常にクロージャが発生します。外側の関数内の変数は、内側の関数によって参照されている限り維持されます。これは、変数が下位スコープからの参照によって強制的に存在する「無人地帯」のようなものですが、隠されています。 Javascript の生来の原則により、より高いスコープから。
クロージャーを使用する方法は他にもいくつかあります。オブジェクト コンストラクターの置き換え、競合のない 1 回限りのプライベート関数などです。ここにはそれらに関する多くの投稿があります。
var yourNamespace = {
func1: function() {
},
func2: function() {
}
};
...
yourNamespace.func1();
この yourNamespace.func1(); のように名前空間から関数を呼び出すことで、必要な関数を呼び出すことができます。