JS中bind,call,apply的用法與實現
阿新 • • 發佈:2021-01-19
JS中bind,call,apply的用法與實現
春招衝刺01.16日 - 01
1. 什麼是bind,call,apply
bind,call,apply是JavaScript中Function物件自帶的三個方法,用於改變函式體內部的 this
指向,也就是函式呼叫時的上下文(context)。
bind,call,apply三者都可以利用後續引數傳參。其中bind不會立即呼叫,而是返回對應的繫結函式,其內的this指向為建立它時傳入bind的 第一個引數,而傳入bind的第二個及以後的引數作為 原函式的引數 來呼叫原函式。
bind(thisArg[, arg1[, arg2[, ...]]])
apply、call則是立即呼叫,改變的this指向他們的第一個引數,apply的第二個引數是一個引數陣列,call的第二個及其以後的引數都是數組裡面的元素。
call ( thisArg, arg1, arg2, ... )
apply ( thisArg ,[argArray] )
2. call的應用與實現
在call的語法call ( thisArg, arg1, arg2, ... )
中,thisArg的傳遞情況有:
- null,undefined或不傳 此時指向window
- 傳遞另一個函式B的函式名,函式中的this指向B的引用
- 傳遞字串、數值或布林型別等基礎型別,函式中的this指向其對應的包裝物件,如 String、Number、Boolean
- 傳遞一個物件,函式中的this指向這個物件
常用方法:
function pChain (){ this.name="pChainRoot"; this.nameprint=function(){ console.log('列印的名字是',this.name); } } var newname={name:"PChainChild"}; var PChain=new pChain(); PChain.nameprint.call(newname); //PChainChild PChain.nameprint(); //pChainRoot
模擬實現:
Function.prototype.myCall = function (thisArg,...args){
//thisArg為呼叫mycall方法的函式的this指向
var thisArg = thisArg || window
//將this賦給thisArg的fn屬性
//此處this指代呼叫myCall的function
thisArg.fn = this;
var result = thisArg.fn(args);
delete thisArg.fn;
return result;
}
PChain.nameprint.myCall(newname); //pChainChild
3. apply的應用與實現
apply與call的作用是一樣的,不過二者接收引數的方法不一樣,apply要求將call的剩餘引數儲存在一個數組中。
當明確知道引數數量時用 call ,而不確定的時候用 apply,並將把引數 push 進陣列傳遞進去,使函式內部也通過 arguments 這個陣列來遍歷所有的引數。
常用方法:
function pChain2 (name1,name2){
this.name1=name1;
this.name2=name2;
this.nameprint=function(){
console.log('列印的名字是',this.name1+'與'+this.name2);
}
}
function pChainChild2 (){
this.name1="PChainChild1";
this.name2="PChainChild2";
var PChain2 = new pChain2("pChainRoot1","pChainPoot2");
//call的傳參方法
PChain2.nameprint.call(this,name1,name2); //PChainChild1與PChainChild2
PChain2.nameprint(); //pChainRoot1與pChainPoot2
//apply的傳參方法
PChain2.nameprint.apply(this,[name1,name2]); //PChainChild1與PChainChild2
}
pChainChild2();
模擬實現:
Function.prototype.myApply = function(thisArg){
//thisArg為呼叫mycall方法的函式的this指向
var thisArg = thisArg || window
//將this賦給thisArg的fn屬性
//此處this指代呼叫myCall的function
thisArg.fn = this;
var result;
if (arguments[1]) {
result = thisArg.fn(arguments[1]);
} else {
result = thisArg.fn();
}
delete thisArg.fn;
return result;
}
4. bind的應用與實現
bind是在es5中擴充套件的方法(IE6,7,8不支援),但是返回值是函式。
常用方法:
var bar= function () {
console.log(this.x);
}
var foo = {
x:3
}
bar(); //undefined
bar.bind (foo) (); //3
要注意的是多次 bind() 是無效的。
var foo2 = {
x:5
}
bar.bind (foo).bind (foo2) (); //3
模擬實現:
Function.prototype.myBind=function(){
var _this = this;
var context = [].shift.call(arguments);// 儲存需要繫結的this上下文
var args = [].slice.call(arguments); //剩下引數轉為陣列
return function(){
_this.apply(context, [].concat.call(args, [].slice.call(arguments)));
}
}