apply, bind, call方法剖析

2022-09-08 00:36:28 字數 4867 閱讀 3391

是三種改變函式內部this指向(即函式執行時所在作用域)的方法。

//

模擬原始碼/**

* 1. 讓函式立即執行

* 2. 改變函式內部的this指向

*/function.prototype.call = function

call(context)

context = context ?object(context) : window;

context.fn = this; //

改變函式內部的this指向

const args =;

for(let i=1; i)

//立即執行;利用了陣列的tostring()屬性

const r = eval('context.fn('+ args + ')');

delete

context.fn;

return

r;

}

1)第乙個引數

第乙個引數必須是物件,

var n = 123;

var obj =

function

a()

//this === window

a.call(); //

window

a.call(null); //

window

a.call(undefine); //

window

a.call(window); //

window

//this === obj

a.call(obj); //

obj//

this === 包裝物件

a.call(5); //

number(5)

2) 其餘的引數

其餘的引數作為函式呼叫時傳入的引數

function

add(a,b)

//this表示固定當前this的指向; this === window

add.call(this, 1, 2); //

3

3)應用

//

呼叫物件的原生方法var obj =

console.log(obj.hasownproperty('tostring')); //

fasle

obj.hasownproperty = function()

console.log(obj.hasownproperty('tostring')); //

true

//obj可以使用原型鏈上的方法,表示在obj的作用域使用hasownproperty的方法

console.log(object.prototype.hasownproperty.call(obj)); //

false

//

模擬原始碼/**

* 3. 引數以陣列形式傳遞 */

//throw

new typeerror('the first param should be a function');

} context = context ?object(context) : window;

context.fn = this;

if(!args)

const r = eval('context.fn('+ args +')');

delete

context.fn;

return

r;}

1)第乙個引數和call方法規則相同

2)第二個引數

function

add(a,b)

null, [1, 2, 3, 4, 5]);

第二個引數還可以是類陣列,如arguments

function

add(a,b)

function

newadd()

var result = newadd(3,4,5,5);

console.log(result);

//7

3)應用

//

1) 查詢陣列的最大值

const arr = [1,3,5];

null, arr); //5//

還可以math.max(...arr); //5//

2) 將陣列的空項轉為undefined;undefine可以被遍歷,空會被遍歷函式忽略

const arr = [1,,4];

null, arr); //

[1,undefined,4] array是陣列的建構函式

//

模擬原始碼/**

* 1. bind可以繫結this的指向;bind還可以繫結引數;

* 最後的引數=bind時傳入的引數+新函式的引數

* 2. bind繫結後返回乙個新的函式

* 3. 如果返回的函式被使用了new命令,this指向例項物件

* 4. new命令生成的例項可以找到原有類的原型物件 */

function.prototype.bind = function

bind(context)

return

};//

新生成的函式繼承bind之前的原型物件

function

fn() {}

fn.prototype = this

.prototype;

boundfn.prototype = new

fn();

//返回新函式

return

boundfn;

}

1)第乙個引數

2)剩餘的引數

當bind(thisvalue, ...)後面引數的個數小於原函式的個數時,繫結部分引數;

//

繫結部分引數;相當於引數復用,只需要處理剩餘的引數

function

fn(a,b)

var newfn = fn.bind(null, 5)

/*newfn = function(b)

*/console.log(newfn(6)); //

11

3)應用

document.addeventlistener('click', obj.fn.bind(this

))//

下面取消繫結無效;因為是不同的函式

document.removeeventlistener('click',obj.fn.bind(this))

正確的寫法寫法應該是

var listener = obj.fn.bind(this

);document.addeventlistener('click', listener);

document.removeeventlistener('click', listener);

obj.print = function

() .bind(

this

));};

obj.print()

//張三

//張三

//張三

[1, 2, 3].slice(0, 1) //

[1]//

等同於array.prototype.slice.call([1, 2, 3], 0, 1) //

[1]//

上面**的意思是在array.prototype.slice物件上呼叫call方法//即

var myslice =function.prototype.call.bind(array.prototype.slice);

console.log(myslice([1,2,3], 0, 1)) // 能呼叫slice的物件是第乙個引數

//同理

var mypush =function.prototype.call.bind(array.prototype.push);

//bind方法傳參也可以被改變

function

f()

var obj =

var mybind =function.prototype.call.bind(function.prototype.bind); // 能呼叫bind方法只能是function

mybind(f, obj)();

//1

2)bind方法是返回乙個新的函式,並不立即執行

應用:1)將類陣列轉為陣列

//

1)將類陣列轉為陣列

//bind方法生成乙個新的函式,需要手動執行,後面加()

array.prototype.slice.bind()();

2)給**函式繫結物件

//

2)繫結**函式的物件;//

未進行繫結前,**函式中的this一般都是windowvar name = 'hello world';

var obj =)

}}obj.print();

//

使用bind方法繫結**函式中的thisvar name = 'hello world';

var obj =.bind(this))) //}}

obj.print();

//var name = 'hello world';

var obj =).call(that); //

})) }

}obj.print();

apply,bind,call應用小總結

一 最大最小 為什麼 二 將偽陣列轉化為陣列 var arraylike 必須以數字為屬性,必須有length屬性,length多了,就會多加undefined,length少了主動刪減多餘的 var arr array.prototype.slice.call arraylike arr為 1 2...

方法的呼叫 this方法 構造方法

1 呼叫者和被呼叫者方法位於同一類中,呼叫形式如下 this 方法名 在大多數情況下,關鍵字this可以忽略 呼叫者位於被呼叫方法所在類的外部 物件名.方法名或者類名.方法名 抽象類只能作為父類,不能例項化。只能被繼承 抽象方法是一種只有方法宣告而沒有方法體定義的特殊方法,最後有乙個分號 而沒有方法...

例項方法 靜態方法 類方法

首先新建乙個日期date類,屬性為年,月,日,tomorrow 是例項方法,這個最常見,比較簡單,例項方法的第乙個引數是例項物件self 當我們傳入的年月日是2018 6 4這樣的形式,我們就需要先進行字串處理,在這裡使用了元組的拆包 這是最基本的方式,但是這樣寫會有乙個問題,每次傳參都需要進行字串...