JavaScript深入なbindのシミュレーション実現
5092 ワード
JavaScript深入なbindのシミュレーション実現
bind()メソッドは、関数を作成します.この新しい関数が呼び出されると、bind()の最初のパラメータは彼の運転時のthisとなります.その後のシーケンスパラメータは、伝達パラメータの前に彼のパラメータとして使用されます.
実はこれもビッド関数の二つの特徴が見られます.は、新しい関数 を返します.は、パラメータ に入ることができる.
まず例を見ます.戻り関数の実現です.
まず騒ぎ立てるビッドを見て、先ほどの騒例を続けます.
一つのバインディング関数もnewオペレータを使用してオブジェクトを作成することができます.このような挙動は、関数をビルダとして扱い、提供されたthis値を無視しながら、呼び出し時のパラメータをアナログ関数に提供します.
つまり、bindが返した関数がコンストラクタとしている場合、bindで指定されたthis値は無効になりますが、入ってきたパラメータは依然として有効です.
しかし、この書き方では、fBound.prototype=this.prototypeを直接修正しても、バインディング関数のprototypeを直接修正します.この時、私達は一つの空の関数で中継できます.
JavaScript深入なbindのシミュレーション実現
bind()メソッドは、関数を作成します.この新しい関数が呼び出されると、bind()の最初のパラメータは彼の運転時のthisとなります.その後のシーケンスパラメータは、伝達パラメータの前に彼のパラメータとして使用されます.
実はこれもビッド関数の二つの特徴が見られます.
まず例を見ます.戻り関数の実現です.
var foo = {
value : 2
}
function bar(){
console.log(this.value)
}
var bindBar = bar.bind(foo)
bindBar();
// 2
私たちが定義したbind 2の関数はFuntions.prototypeで定義します.私たちの関数はすべてFunctionによって作成されました.windowもFunction.prototypeの例です.window.__proto__.__proto__.__proto__.__proto__.__proto__ == Object.prototype.__proto__
//true
Object.__proto__ == Function.prototype
//true
window.__proto__.__proto__.__proto__.__proto__ == Function.prototype.__proto__
//true
Function.prototype.bind2 = function(context){
console.log(111, this)
// this 。 bar , bar
//context
//bar this context this
var self = this
return function(){
self.apply(context)
}
}
var foo = {
value:3
}
function bar(){
console.log(this.value)
}
var bindFoo = bar.bind2(foo);
//bind2 bind2 ,
console.log(bindFoo()) //3
参考文献のシミュレーション実現まず騒ぎ立てるビッドを見て、先ほどの騒例を続けます.
var foos = {
value:4
}
function foo(name,age){
console.log(name)
console.log(age)
console.log(this.value)
}
var bindFoo = foo.bind(foos, 'xiaolizi')
bindFoo(18)
// xiaolizi
//18
// 4
fooはnameとageの二つのパラメータが必要です.そして、bindの時に、一つのnameだけを伝えて、戻ってきた関数を実行する時に、もう一つのパラメータageを伝えます.ですから、もう二番目のバージョンはアーグメンントを処理する必要があります.
Function.prototype.bind2 = function(context){
var self = this;
// arguments , slice, call this
// slice(1) , context。
var args = Array.prototype.slice.call(arguments,1)
return function(){
// ,
var bindArgs = Array.prototype.slice.call(arguments)
return self.apply(context,args.concat(bindArgs))
}
}
var foos = {
value:4
}
function foo(name,age){
console.log(name)
console.log(age)
console.log(this.value)
}
var bindFoo = foo.bind2(foos, 'xiaolizi')
bindFoo(18)
コンストラクタ効果のシミュレーション実現一つのバインディング関数もnewオペレータを使用してオブジェクトを作成することができます.このような挙動は、関数をビルダとして扱い、提供されたthis値を無視しながら、呼び出し時のパラメータをアナログ関数に提供します.
つまり、bindが返した関数がコンストラクタとしている場合、bindで指定されたthis値は無効になりますが、入ってきたパラメータは依然として有効です.
var value = 2;
var foo = {
value: 1
};
function bar(name, age) {
this.habit = 'shopping';
console.log(this.value);
console.log(name);
console.log(age);
}
bar.prototype.friend = 'kevin';
var bindFoo = bar.bind(foo, 'daisy');
var obj = new bindFoo('18');
// undefined
// daisy
// 18
console.log(obj.habit);
console.log(obj.friend);
// shopping
// kevin
注意:グローバルとfooでvalue値を宣言しましたが、最後にundefindに戻りました.紐付けのthisが失効したと説明しています.newのシミュレーションが実現されていることを知ると、この時のthisがObjを指していることが分かります.//
Function.prototype.bind2 = function (context) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
// ,this , true, this ,
// demo , `this instanceof fBound ? null : context`, , null this , habit
// ,this window, false, this context
return self.apply(this instanceof fBound ? this : context, args.concat(bindArgs));
}
// prototype prototype,
// fBound function, , , this , ,this fBound.prototype this
fBound.prototype = this.prototype;
return fBound;
}
コンストラクタ効果の最適化実現しかし、この書き方では、fBound.prototype=this.prototypeを直接修正しても、バインディング関数のprototypeを直接修正します.この時、私達は一つの空の関数で中継できます.
//
Function.prototype.bind2 = function (context) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
最終版Function.prototype.bind2 = function (context) {
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
以上は文章を参考にして自分の理解を加えました.JavaScript深入なbindのシミュレーション実現