call、apply、bind 原理、區別及原生js模擬。

Function的prototype原型上存放着 Function實例 的一些共有方法。
A.Function的原型不像其餘類(Array、Object...)的原型同樣是個對象,Fuction的原型是一個空函數,是能夠執行的,只不過返回undefined,Function.prototype();可是這並不影響它做爲一個對象擁有本身的屬性方法
B.Function這個類,同時也是Function的一個實例,因此它也具有__proto__屬性,這個屬性指向它本身的原型數組

1.call方法。每一個函數均可以調用call方法,來改變當前這個函數執行的this關鍵字,而且支持傳入參數;咱們用原生js模擬call方法,來更加深入瞭解它。
a.第一個參數爲調用call方法的函數中的this指向
b.第二個及之後的參數爲給調用call方法的函數傳入的參數
c.執行這個函數,call方法返回的結果就是 調用他的函數返回的結果
d.將this指向銷燬。app

Function.prototype.mycall = function(context){
    context = context || window;
    context.fn = this;
    var arr = [];
    for(var i = 1;i<arguments.length;i++){
        arr.push('arguments['+i+']');
    }
    var result = eval('context.fn('+arr.toString()+')');
    delete context.fn;
    return result;
}
var obj = {name:'qiaoshi'};
var a = {sex:1}
function say(n){
    console.log(this,n);
}
say.mycall(obj,a)

2.apply和call方法相似,做用都是改變當前函數執行的this指向,而且將函數執行。
惟一不一樣就是 call方法給當前函數傳參是一個一個傳。而apply是以數組方式傳入參數函數

Function.prototype.myApply =function(context,arr){
context = Object(context) || window;
context.fn = this;
var result;
if(!arr){
    result= context.fn();
}else{
    var args = [];
    for(var i=0;i<arr.length;i++){
        args.push('arr['+i+']');
    }
    result = eval('context.fn('+args.toString()+')')
}
delete context.fn;
return result;
}

var q = {name:'chuchu'};
var arg1 = 1;
var arg2= [123]
function eat(n,m){
    console.log(this,n,m);
}
eat.myApply(q,[arg1,arg2])

3.bind方法,是改變當前調用bind方法的函數this指向,可是不會當即執行當前函數,而是返回一個新的函數。而且支持給新的函數傳入參數執行,從而出發以前調用bind方法的函數執行,而且參數透傳進去。bind方法是高階函數的一種。this

Function.prototype.myBind = function(){
var context = arguments[0];
var self = this;
return function (){
    self.myApply(context,arguments)
}
};
var j = {name:1};
var k = [123]
function drink (k){
    console.log(this.name,k);
}
var fn = drink.myBind(j);
fn(k);

實現原生 call、apply、bind方法的重點:
1.改變this指向:函數執行,點.前面是誰,this就是誰的原理改變this指向
2.參數透傳:經過eval將字符串轉變成js語法 去執行。
3.bind方法返回一個函數,返回的函數執行,會進行做用域查找context對象;而且經過原型鏈查找調用apply方法prototype

call、apply、bind相同和區別
相同:都能改變函數執行的this指向
不一樣:callapply 是當即執行 bind是不執行code

call傳參是一個一個傳入,apply是數組形式傳入對象

相關文章
相關標籤/搜索