JSシミュレーション実現call,apply,bind
前言
私はcall、applay、bindの3つの前の使い方と区別について、仲間たちはきっとよく知っていると信じています.結局、これも面接の高周波試験問題です.前の面接の時、面接官がcallに言及したとき、私は怒っていました.冗談を言う準備をしていたとき、面接官はjsでcallの使い方をシミュレートしてくださいと言いました.5分までです.その时はぼんやりしていて、頭の中にはいろいろな使い方しかありませんでしたが、内部でどのように実現したのか、まだ研究したことがありません.その时、自分に冷たい歌を歌いました.失敗は怖くないので、今日は自分が亡くなった面接を記念して特筆します.
Call
関数の実行コンテキストを変更することは、ある関数の指定を特定のオブジェクトの下で実行することに相当します.
Apply
bind
bind()メソッドは新しい関数を作成します.この新しい関数が呼び出されるとbind()の最初のパラメータが実行時のthisとして使用され、その後のシーケンスパラメータが伝達された実パラメータの前にそのパラメータとして送信されます.すなわちbind関数の特徴は,パラメータを伝達できる関数を返すことである.また、バインド関数はnewオペレータを使用してオブジェクトを作成することもできます.この動作は、元の関数をコンストラクタとして使用するのと同じです.指定したthis値は無視され、呼び出し時のパラメータはシミュレーション関数に提供されます.
New——参考リンク
【注意】参考文書:https://github.com/mqyqingfeng/Blog/issues/11
私はcall、applay、bindの3つの前の使い方と区別について、仲間たちはきっとよく知っていると信じています.結局、これも面接の高周波試験問題です.前の面接の時、面接官がcallに言及したとき、私は怒っていました.冗談を言う準備をしていたとき、面接官はjsでcallの使い方をシミュレートしてくださいと言いました.5分までです.その时はぼんやりしていて、頭の中にはいろいろな使い方しかありませんでしたが、内部でどのように実現したのか、まだ研究したことがありません.その时、自分に冷たい歌を歌いました.失敗は怖くないので、今日は自分が亡くなった面接を記念して特筆します.
Call
関数の実行コンテキストを変更することは、ある関数の指定を特定のオブジェクトの下で実行することに相当します.
Function.prototype.call = function (context) {
let context = context || window;
context.fn = this;
let args = [];
for(let i = 1, len = arguments.length; i < len; i++) {
let temp = 'arguments['+ i +']';
args.push(temp);
}
let result = eval('context.fn(' + args +')'); // Arrary.toString()
delete context.fn;
return result;
}
Apply
Function.prototype.apply = function (context, arr) {
let context = Object(context) || window;
context.fn = this;
let result;
if (!arr) {
result = context.fn();
} else {
let args = [];
for (let i = 0, len = arr.length; i < len; i++) {
args.push('arr['+ i +']');
}
result = eval('context.fn(' + args + ')')
}
delete context.fn;
return result;
}
bind
bind()メソッドは新しい関数を作成します.この新しい関数が呼び出されるとbind()の最初のパラメータが実行時のthisとして使用され、その後のシーケンスパラメータが伝達された実パラメータの前にそのパラメータとして送信されます.すなわちbind関数の特徴は,パラメータを伝達できる関数を返すことである.また、バインド関数はnewオペレータを使用してオブジェクトを作成することもできます.この動作は、元の関数をコンストラクタとして使用するのと同じです.指定したthis値は無視され、呼び出し時のパラメータはシミュレーション関数に提供されます.
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 () {};
fNOP.prototype = this.prototype;
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fBound.prototype = new fNOP();
return fBound;
}
New——参考リンク
function objectFactory() {
var obj = new Object(),
Constructor = [].shift.call(arguments); // , 。 shift , arguments
obj.__proto__ = Constructor.prototype; // Object.setPrototypeOf(obj, Constructor.prototype)
// ,
// var Fn = new Function();
// Fn.prototype = Constructor.prototype;
// obj = new Fn();
var ret = Constructor.apply(obj, arguments);
return typeof ret === 'object' ? ret||obj : obj; //
};
【注意】参考文書:https://github.com/mqyqingfeng/Blog/issues/11