ホームページ > 記事 > ウェブフロントエンド > Javascript_javascriptスキルにおけるbind()メソッドの使用と実装の簡単な分析
bind() メソッドについて説明する前に、次の質問を見てみましょう:
var altwrite = document.write
altwrite("こんにちは");
//1. 上記のコードのどこが間違っています
//2. 正しい操作は何ですか
//3.bind()メソッドの実装方法
altwrite.bind(document)("hello")
もちろん、call() メソッドを使用することもできます:
この記事の焦点は、3 番目の問題である、bind() メソッドの実装について説明することです。bind() の実装について説明する前に、まず、bind() メソッドの使用方法を見てみましょう。
バインディング関数
this.num = 9; var mymodule = { num: 81, getNum: function() { return this.num; } }; module.getNum(); // 81 var getNum = module.getNum; getNum(); // 9, 因为在这个例子中,"this"指向全局对象 // 创建一个'this'绑定到module的函数 var boundGetNum = getNum.bind(module); boundGetNum(); // 81
部分関数 部分関数は部分アプリケーションとも呼ばれます。部分関数の定義は次のとおりです。
部分的なアプリケーションは、いくつかの引数を受け入れる関数を受け取り、それらの引数の 1 つ以上に値をバインドし、残りのバインドされていない引数のみを受け入れる新しい関数を返すものとして説明できます。
これは非常に優れた機能です。bind() を使用して、関数の事前定義されたパラメーターを設定し、呼び出し時に他のパラメーターを渡します。
function list() { return Array.prototype.slice.call(arguments); } var list1 = list(1, 2, 3); // [1, 2, 3] // 预定义参数37 var leadingThirtysevenList = list.bind(undefined, 37); var list2 = leadingThirtysevenList(); // [37] var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]
通常、setTimeout() の this はウィンドウまたはグローバル オブジェクトを指します。クラス メソッドを使用するときにこれをクラス インスタンスを指す必要がある場合は、bind() を使用してこれをコールバック関数にバインドし、インスタンスを管理できます。
function Bloomer() { this.petalCount = Math.ceil(Math.random() * 12) + 1; } // 1秒后调用declare函数 Bloomer.prototype.bloom = function() { window.setTimeout(this.declare.bind(this), 1000); }; Bloomer.prototype.declare = function() { console.log('我有 ' + this.petalCount + ' 朵花瓣!'); };
バインド関数は、new 演算子を使用してターゲット関数のインスタンスを構築するのにも適しています。バインド関数を使用してインスタンスを構築する場合、これは無視されますが、渡されたパラメーターは引き続き使用できることに注意してください。
function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function() { return this.x + ',' + this.y; }; var p = new Point(1, 2); p.toString(); // '1,2' var emptyObj = {}; var YAxisPoint = Point.bind(emptyObj, 0/*x*/); // 实现中的例子不支持, // 原生bind支持: var YAxisPoint = Point.bind(null, 0/*x*/); var axisPoint = new YAxisPoint(5); axisPoint.toString(); // '0,5' axisPoint instanceof Point; // true axisPoint instanceof YAxisPoint; // true new Point(17, 42) instanceof YAxisPoint; // true
bind() は、特定の this 値を必要とする関数のショートカットを作成することもできます。
たとえば、配列のようなオブジェクトを実際の配列に変換する場合、考えられる例は次のとおりです:
var slice = Array.prototype.slice; // ... slice.call(arguments);
var unboundSlice = Array.prototype.slice; var slice = Function.prototype.call.bind(unboundSlice); // ... slice(arguments);
上記のセクションから、bind() には多くの使用シナリオがあることがわかりますが、bind() 関数は ECMA-262 の第 5 版で追加されただけであり、すべてのブラウザで実行できるわけではありません。そのためには、bind() 関数を自分で実装する必要があります。
まず、ターゲット関数のスコープを指定することで、単純に binding() メソッドを実装できます。
Function.prototype.bind = function(context){ self = this; //保存this,即调用bind方法的目标函数 return function(){ return self.apply(context,arguments); }; };
Function.prototype.bind = function(context){ var args = Array.prototype.slice.call(arguments, 1), self = this; return function(){ var innerArgs = Array.prototype.slice.call(arguments); var finalArgs = args.concat(innerArgs); return self.apply(context,finalArgs); }; };
Function.prototype.bind = function(context){ var args = Array.prototype.slice(arguments, 1), F = function(){}, self = this, bound = function(){ var innerArgs = Array.prototype.slice.call(arguments); var finalArgs = args.concat(innerArgs); return self.apply((this instanceof F ? this : context), finalArgs); }; F.prototype = self.prototype; bound.prototype = new F(); return bound; };
Function.prototype.bind = function (oThis) { if (typeof this !== "function") { throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () {}, fBound = function () { return fToBind.apply( this instanceof fNOP && oThis ? this : oThis || window, aArgs.concat(Array.prototype.slice.call(arguments)) ); }; fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; };