call 函數
語法
obj.call(thisObj,arg[,arg2[,arg3[,...agr]]]);
簡介
修改obj的this指向為thisObj,后面的參數會當成obj的參數安裝順序傳遞進去。
我們先來看一下下面這段代碼會輸出什么:
function say(arg1, arg2) {
? console.log(this.name, arg1, arg2);
}
const obj = {
? name: "tom",
? say: function () {
? ? console.log(this.name);
? }
};
say();
輸出結果:
我們發(fā)現報錯了立膛,程序并沒有找到name;
現在我們來改動一下掌动,使用call函數來改變this的指向德澈,看看會發(fā)生什么:
say.call(obj, "1", "2");
發(fā)現輸出的結果變成了:
call把say函數的this變?yōu)榱薿bj挣棕。
下面我們來實現一個call函數
Function.prototype._call = function (context) {
? // 判斷是否是一個函數
? // this指的是調用的函數
? if (typeof this !== "function") {
????????throw new TypeError("Error");
? }
? context = context || window;
? context.fn = this;
? const args = [...arguments].slice(1);
? const result = context.fn(...args);
? delete context.fn;
? return result;
};
驗證一下:
say._call(obj, "1", "2");
發(fā)現輸出結果與期望的相同
apply函數
語法
obj.call(thisObj[,argArray]);
簡介
apply與call函數的用法相同译隘,只是參數的傳遞變成了數組形式。
say.apply(obj, ["1", "2"]);
輸出的結果與調用call相同:
與call的實現相比洛心,只需要修改一下參數的傳遞:
Function.prototype._apply = function (context, args) {
? // 判斷是否是一個函數
? // this指的是調用的函數
? if (typeof this !== "function") {
? ? throw new TypeError("Error");
? }
? context = context || window;
? context.fn = this;
? let result = null;
? if (args) {
? ? result = context.fn(...args);
? } else {
? ? result = context.fn();
? }
? delete context.fn;
? return result;
};
bind 函數
語法
obj.bind(thisObj,arg[,arg2[,arg3[,...agr]]]);
簡介
bind函數會返回一個新函數固耘,但是不會像call和apply一樣立即執(zhí)行函數,bind后面的參數會當成obj的參數安裝順序傳遞進去。
我們先來看兩段代碼
const s = say.bind(obj, "1", "2");
s()
const s = say.bind(obj);
s("1", "2");
發(fā)現這兩段代碼輸出的結果是一樣的皂甘。
我們來簡單實現一下bind函數:
Function.prototype._bind = function (context) {
? // 判斷是否是一個函數
? if (typeof this !== "function") {
? ? throw new TypeError("Error");
? }
? const args = [...arguments].slice(1);
? const fn = this;
? const F = function () {},
? ? fBound = function () {
? ? ? return fn.apply(
? ? ? ? this instanceof F && context ? this : context || window,
? ? ? ? args.concat(...arguments)
? ? ? );
? ? };
? F.prototype = this.prototype;
? fBound.prototype = new F();
? return fBound;
};