JavaScript this
阿新 • • 發佈:2020-11-04
this用的很多,react 的class component用了這麼多自己也比較熟悉的了,下面就來講講如何判斷一個this的繫結以及call、apply、bind的實現。
判斷this繫結
主要就是以下的五點:
- 由new呼叫:繫結到新建立的物件上面。在類裡面的contructor中,指向將要通過構造器建立的物件。
- 由call、apply、bind來呼叫,繫結到指定的物件上面。
- 由上下文物件呼叫,就繫結到上下文的物件上面。
- 預設:全域性物件,node為global,瀏覽器為window
如何實現call
Function.prototype.call = function(context) { var context = Object(context) || window; // call是由一個函式呼叫的,此時this就指向該函式 context.fn = this; var args = []; for(let i = 1; i < arguments.length; i++) { args.push('arguments[' + i + ']'); } var res = eval('context.fn(' + args + ')'); delete context.fn; return res; } var obj = { a: 1 } function print() { console.log(this.a) } print.call(obj);
如何實現apply
apply與call的最大區別就是,apply僅有第二個引數apply(obj, arguments),且arguments為一個數組,數組裡面存放了要傳遞給呼叫call方法的函式的引數
而call則一個一個的接收引數call(obj, argument1, argument2, argument3, ... argumentn)
Function.prototype.apply = function(context, arr) { var context = Object(context) || window; context.fn = this; var res; if(!arr) { res = context.fn(); } else { var args = []; for(let i = 0; i < arr.length; i++) { args.push('arr[' + i + ']'); } res = eval('context.fn(' + args + ')'); } delete context.fn; return res; } var obj = { a: 1 } function bar(b, c) { return { a: this.a, b: b, c: c } } bar.apply(obj, [2,3])
如何實現bind
Function.prototype.bind = 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.call(arguments, 1); var fNOP = function() {}; var fBound = function() { self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments))); } fNOP.prototype = this.prototype; fbound.prototype = new fNOP(); return bound; }