一昨日面接に行ったのですが、gg から js の知識について質問されました。call メソッドを 365 日前に使用したことがありましたが、まだ答えることができませんでした。その時は今日は詳しくまとめます。
call と apply の機能は、関数を別のオブジェクトにバインドして実行することです。
両方の形式とパラメータ定義は次のとおりです。
call( thisArg [, arg1, arg2, ... ] ); // パラメータリスト, arg1, arg2, ...
apply(thisArg [, argArray] ); // パラメータ配列、argArray
上記 2 つの関数内の this ポインタには thisArg が割り当てられ、関数を別のオブジェクトのメソッドとして実行するという目的を実現できます。
1.通話の簡単な使い方
まず、簡単な例 (呼び出し) を見てみましょう。
次のようにコードをコピーします。
<!doctype html>
<html>
<頭>
<title> 呼び出し-適用 </title>
</head>
<本文>
<input type="text" id="idTxt" value="入力テキスト">
<script type="text/javascript">
var 値 = "グローバル変数";
関数 mFunc()
{
this.value = "メンバー変数";
}
関数 gFunc()
{
アラート(この値);
}
window.gFunc();// gFunc、グローバル変数を表示
gFunc.call(window);// gFunc、グローバル変数を表示
gFunc.call(new mFunc());// mFunc、メンバー変数を表示
gFunc.call(document.getElementById('idTxt'));// 要素を表示、入力テキスト
</script>
<スクリプト言語="javascript">
var func = 新しい関数()
{
this.a = "機能";
}
var func2 = 関数(x)
{
var a = "関数2";
アラート(this.a);
アラート(x);
}
func2.call(func, "func2");// func と func2 を表示
</script>
</body>
</html>
そして、実行結果は次のようになります。
グローバル変数グローバル変数
メンバー変数
テキストを入力する
機能
機能2
テスト環境:Google Chrome10.0.648.45
最後に結果を分析します
1. グローバル オブジェクト window は関数 gFunc を呼び出します。これは window オブジェクトを指すため、this.value はグローバル変数です。
2. 関数 gFunc は call メソッドを呼び出します。これはデフォルトで最初のパラメータ ウィンドウ オブジェクトを指すため、this.value もグローバル変数です。
3. 関数 gFunc は call メソッドを呼び出します。これはデフォルトで mFunc のオブジェクトである最初のパラメーター new mFunc() になります。したがって、this.value は mFunc のメンバー変数になります。
4. 関数 gFunc は call メソッドを呼び出します。デフォルトでは、this.value は最初のパラメーターの入力テキスト コントロール、つまり id='idTxt' を持つコントロールを指します。そのため、this.value は入力コントロールの値入力テキストになります。
5. 関数 func2 は call メソッドを呼び出します。これはデフォルトで最初のパラメーター func 関数オブジェクトになるため、this.value は this.a (func) になります。
6. 関数 func2 は call メソッドを呼び出します。2 番目のパラメータは関数オブジェクト func2 のパラメータに属するため、alert(x) は 2 番目のパラメータ func2 です。
2. コール継承の使用法と改善
js は呼び出しを使用して継承をシミュレートします
テストコード:
次のようにコードをコピーします。
<!doctype html>
<html>
<頭>
<title> 呼び出し - 継承を申請する </title>
</head>
<本文>
<script type="text/javascript">
関数baseA()//ベースクラスA
{
this.member = "baseA メンバー";
this.showSelfA = function()
{
window.alert(this.member);
}
}
関数baseB()//ベースクラスB
{
this.member = "baseB メンバー";
this.showSelfB = function()
{
window.alert(this.member);
}
}
function extendAB()// A と B からクラスを継承
{
baseA.call(this);// A を呼び出します
baseB.call(this);// B を呼び出します
}
window.onload = 関数()
{
var extend = new extendAB();
extend.showSelfA();// A を表示
extend.showSelfB();// B を表示
}
</script>
</body>
</html>
実行結果は次のとおりです。ベースBメンバー
ベースBメンバー
テスト環境:Google Chrome10.0.648.45
結果分析:
期待される結果は、baseA メンバーとbaseB メンバーを出力することですが、実際の出力は、baseB メンバーとbaseB メンバーです。
(IE9、8、6、Maxthon、Chrome、FF、Opera、Safari、360、およびその他のブラウザでテストされており、結果は後者です:baseB メンバー)
現時点ではマシンは間違っていないため、詳細な分析を行う必要があります。
これは、baseB オブジェクトを 2 回ポイントしていることが原因であると簡単に考えられますが、実際はそうなのでしょうか。
本質を探るため、Chrome ブラウザのデバッグ ツールを使用してブレークポイントを設定してデバッグしたところ、次のことがわかりました。
extend.showSelfA(); が呼び出されると、これは extendAB を指します (2 回推測したように、baseB オブジェクトを指しません)。
本当の理由は、extendAB オブジェクトのメンバ変数 member が、baseB.call(this) によってインスタンス化されるときに、baseB のメンバ メンバによって上書きされるためです。つまり、extendAB のメンバ メンバが、baseA メンバからBaseBメンバー。
もちろん、上記の BaseA コードを少し変更して、デバッグ分析の正確さを検証することもできます。
次のようにコードをコピーします。
関数baseA()//ベースクラスA
{
this.memberA = "baseA member" // メンバーは、baseB のメンバーと区別するために memberA に変更されます。
this.showSelfA = function()
{
window.alert(this.memberA); // memberA を表示します。
}
}
Chrome などのブラウザを再度実行すると、結果は次のようになります。
ベースAメンバー
ベースBメンバー
結果は期待どおりであり、Chrome のデバッグ情報によっても正確さが検証されます。
継承の改善(プロトタイプ)
上記のシミュレートされた継承方法は、注意深く分析した結果、最善のものではありません。
関数(クラス)にメンバメソッドを定義するたびにインスタンスのコピーが発生するため、プロトタイプのプロトタイプを利用して改良を加えることができます。
改善例としては以下のようなものがあります。
次のようにコードをコピーします。
<!doctype html>
<html>
<頭>
<title> 電話 - プロトタイプの申請 </title>
</head>
<本文>
<script type="text/javascript">
varClass = {
create: function()// 関数を作成
{
戻り関数()
{
this.initialize.apply(this, 引数);
}
}
};
var person = Class.create();// クラス person を作成します
Person.prototype = {// プロトタイプの初期化
初期化: function(obj1, obj2)
{
this.obj1 = obj1;
this.obj2 = obj2;
}、
showSelf: 関数()
{
alert("obj: " + this.obj1 + " および " + this.obj2);
}
}
// インスタンスクラス
var person = new Person("man", "women");// 2 つのパラメータ
person.showSelf();// 人物を表示
</script>
</body>
</html>
実行結果は次のとおりです。
オブジェクト: 男性と女性