ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript でのいくつかの借用メソッドの詳細な説明 (グラフィック チュートリアル)

JavaScript でのいくつかの借用メソッドの詳細な説明 (グラフィック チュートリアル)

亚连
亚连オリジナル
2018-05-19 16:11:171355ブラウズ

JavaScript でのメソッドの借用について詳しく見てみましょう。 注: この記事は、call()、apply()、bind() の使用に関する関連知識とそれらの違いを習得していることを前提としています。 JavaScriptでの借用方法を知ることができます。

はじめに

call()、apply()、bind() メソッドを通じて、これらのオブジェクトからメソッドを継承せずに、他のオブジェクトからメソッドを簡単に借用できます。

JavaScript でのメソッドの借用

JavaScript では、他のオブジェクトの関数やメソッドを再利用できる場合がありますが、これらは必ずしもオブジェクト自体またはプロトタイプで定義する必要はありません。 call()、apply()、bind() メソッドを使用すると、メソッドを継承せずに他のオブジェクトから簡単に借用できます。これは、プロの JavaScript 開発者が使用する一般的なアプローチです。

プロトタイプメソッド

JavaScriptでは、文字列、数値、ブール値などの不変のプリミティブデータ型を除き、ほぼすべてのデータがオブジェクトです。 Array は、順序付けされたシーケンスの走査と変換に適したオブジェクトです。そのプロトタイプには、slice、join、push、pop などの便利なメソッドがあります。

一般的な例は、オブジェクトと配列が両方ともリスト型データ構造である場合、オブジェクトは配列からメソッドを「借りる」ことができます。最も一般的に借用されたメソッドは Array.prototype.slice です。 Array.prototype.slice

function myFunc() {
 
  // error, arguments is an array like object, not a real array
  arguments.sort();
 
  // "borrow" the Array method slice from its prototype, which takes an array like object (key:value)
  // and returns a real array
  var args = Array.prototype.slice.call(arguments);
 
  // args is now a real Array, so can use the sort() method from Array
  args.sort();
 
}
 
myFunc('bananas', 'cherries', 'apples');

借用方法之所以可行,是因为 call 和 apply 方法允许在不同上下文中调用函数,这也是重用已有功能而不必继承其它对象的好方法。实际上,数组在原型中定义了很多常用方法,比如 join 和 filter 也是:

// takes a string "abc" and produces "a|b|c
Array.prototype.join.call('abc', '|');
 
// takes a string and removes all non vowels
Array.prototype.filter.call('abcdefghijk', function(val) {
  return ['a', 'e', 'i', 'o', 'u'].indexOf(val) !== -1;
}).join('');

可以看出,不仅对象可以借用数组的方法,字符串也可以。但是因为泛型方法是在原型上定义的,每次想要借用方法时都必须使用 String.prototype Array.prototype。这样写很啰嗦,很快就会令人生厌。更有效的方法是使用字面量来达到同样的目的。

使用字面量借用方法

字面量是一种遵循JavaScript规则的语法结构,MDN 这样解释:

在JavaScript中,使用字面量可以代表值。它们是固定值,不是变量,就是在脚本中按字面给出的。
字面量可以简写原型方法:

[].slice.call(arguments);
[].join.call('abc', '|');
''.toUpperCase.call(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');

这样看上去没有那么冗长了,但是必须直接在 [] 和 "" 上操作以借用方法,仍然有点丑。可以利用变量保存对字面量和方法的引用,这样写起来更简便些:

var slice = [].slice;
slice.call(arguments);
var join = [].join;
join.call('abc', '|');
 
var toUpperCase = ''.toUpperCase;
toUpperCase.call(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');

有了借用方法的引用,我们就可以轻松地使用 call() 调用它了,这样也可以重用代码。秉着减少冗余的原则,我们来看看可否借用方法却不用每次调用都要写 call() 或者 apply():

var slice = Function.prototype.call.bind(Array.prototype.slice);
slice(arguments);
 
var join = Function.prototype.call.bind(Array.prototype.join);
join('abc', '|');
 
var toUpperCase = Function.prototype.call.bind(String.prototype.toUpperCase);
toUpperCase(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');

如你所见,现在可以使用 Function.prototype.call.bind 来静态绑定从不同原型“借来的”方法了。但是 var slice = Function.prototype.call.bind(Array.prototype.slice) 这句话实际是如何起作用的呢?

理解 Function.prototype.call.bind

Function.prototype.call.bind 乍一看有些复杂,但是理解它是如何起作用的会非常有益。

Function.prototype.call 是一种引用,可以“call”函数并将设置其“this”值以在函数中使用。
注意“bind”返回一个存有其“this”值的新函数。因此 .bind(Array.prototype.slice)

var scoreCalculator = {
  getSum: function(results) {
    var score = 0;
    for (var i = 0, len = results.length; i < len; i++) {
      score = score + results[i];
    }
    return score;
  },
  getScore: function() {
    return scoreCalculator.getSum(this.results) / this.handicap;
  }
};
var player1 = {
  results: [69, 50, 76],
  handicap: 8
};
 
var player2 = {
  results: [23, 4, 58],
  handicap: 5
};
 
var score = Function.prototype.call.bind(scoreCalculator.getScore);
 
// Score: 24.375
console.log(&#39;Score: &#39; + score(player1));
 
// Score: 17
console.log(&#39;Score: &#39; + score(player2));

call メソッドと apply メソッドを使用すると、異なるコンテキストで関数を呼び出すことができるため、メソッドの借用が機能します。これは、他のオブジェクトから継承することなく、既存の機能を再利用する良い方法でもあります。実際、配列は、結合やフィルターなど、プロトタイプで多くの一般的なメソッドを定義しています。

rrreee オブジェクトだけでなく、文字列からもメソッドを配列から借用できることがわかります。ただし、ジェネリック メソッドはプロトタイプで定義されているため、メソッドを借用するたびに String.prototype または Array.prototype を使用する必要があります。このように書くと冗長になるため、すぐに飽きてしまいます。より効率的な方法は、同じ目的を達成するためにリテラルを使用することです。

リテラル借用メソッドを使用する

リテラルは、JavaScript ルールに従った構文構造です。

JavaScript では、リテラルを使用して値を表すことができます。これらは固定値、変数、またはスクリプト内で文字通り指定されます。

リテラルはプロトタイプ メソッドを省略できます:

rrreee

これはそれほど冗長には見えませんが、メソッドを借用するために [] と "" を直接操作しなければならないのは、やはり少し見苦しいです。変数を使用してリテラルやメソッドへの参照を保存すると、次の記述が容易になります。

rrreee

借用したメソッドへの参照を使用すると、call() を使用して簡単に呼び出すことができ、再利用することもできます。コード。冗長性を減らすという原則に従って、呼び出されるたびに call() や apply() を書かずにメソッドを借用できるかどうかを見てみましょう:

rrreee🎜🎜🎜 ご覧のとおり、 を使用できるようになりました。 >Function .prototype.call.bind は、異なるプロトタイプから「借用した」メソッドを静的にバインドします。しかし、 varlice = Function.prototype.call.bind(Array.prototype.slice) という文は実際にはどのように機能するのでしょうか? 🎜🎜🎜Function.prototype.call.bind について理解する🎜🎜🎜Function.prototype.call.bind は最初は複雑に思えるかもしれませんが、その仕組みを理解することは非常に有益です。 🎜🎜Function.prototype.call は、関数を「呼び出し」、その関数で使用する「this」値を設定する参照です。 🎜「bind」は「this」値を持つ新しい関数を返すことに注意してください。したがって、 .bind(Array.prototype.slice) によって返される新しい関数の「this」は常に Array.prototype.slice 関数になります。 🎜🎜🎜要約すると、🎜新しい関数は「call」関数を呼び出し、その「this」は「slice」関数です。 slide() を呼び出すと、以前に修飾されたメソッドが参照されます。 🎜🎜🎜🎜🎜カスタムオブジェクトのメソッド🎜🎜🎜🎜継承は優れていますが、開発者は通常、一部のオブジェクトやモジュール間で共通の機能を再利用したい場合にそれを使用します。単純な借用方法はほとんどの場合複雑になるため、コードを再利用するためだけに継承を使用する必要はありません。 🎜🎜以前はネイティブ メソッドの借用についてのみ説明しましたが、どのメソッドの借用も可能です。たとえば、次のコードはポイント ゲームのプレーヤーのスコアを計算できます: 🎜🎜🎜rrreee🎜🎜🎜上記の例は非常に率直ですが、ネイティブ メソッドと同様に、ユーザー定義メソッドも簡単に借用できることがわかります。 🎜🎜🎜概要🎜🎜🎜Call、bind、apply は関数の呼び出し方法を変更することができ、関数を借用するときによく使用されます。ほとんどの開発者はネイティブ メソッドを借用することに慣れていますが、カスタム メソッドを借用することはそれほど多くありません。 🎜🎜上記は私があなたのためにまとめたものです。 🎜🎜関連記事: 🎜🎜🎜jsの組み込みオブジェクトMathのプロパティとメソッドについて詳しく話す(一目瞭然)🎜🎜🎜

JavaScriptを使用してパターンマッチングのStringメソッドを実装します

JavaScriptの詳細な説明(グラフィックチュートリアル)

以上がJavaScript でのいくつかの借用メソッドの詳細な説明 (グラフィック チュートリアル)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。