call的實現原理

2021-10-06 08:21:22 字數 4005 閱讀 6081

下面我們來看乙個例子

let body = document.body;

let obj =

;function

func

(x, y)

body.οnclick=func和body.click=func()的區別bind原理和思想// 執行bind(bind中的this是要操作的函式),返回乙個匿名函式給事件繫結或者其它的內容,當事件觸發的時候,首先執行的是匿名函式(此時匿名函式中的this和bind中的this是沒有關係的)

// bind的內部機制就是利用閉包(柯理化函式程式設計思想)預先把需要執行的函式以及改變的this再以及後續需要給函式傳遞的引數資訊等都儲存到不釋放的上下文中,後續使用的時候直接拿來用,這就是經典的預先儲存的思想

function.prototype.

bind

=function

bind

(context = window,

...params);}

;body.onclick = func.

bind

(obj,10,

20);

body.onclick = func.bind(obj, 10, 20); //將bind方法繫結給

原理:func.bind(obj, 10, 20)這個帶了括號,表示執行bind的方法,即執行anonymous匿名函式,匿名函式中觸發了 func.call(obj,10,20,ev)函式執行

body.onclick = function anonymous(ev) ;

settimeout(func.bind(obj), 1000);//將func.bind(obj)方法繫結給定時器

原理:1秒鐘後執行匿名

settimeout(function anonymous() , 1000);

// 我不是某個類的例項,不能直接用它原型上的方法,但是我可以讓某個類原型上的方法執行,讓方法中的this(一般是需要處理的例項)變為我,這樣就相當於我在借用這個方法實現具體的功能 這種借用規則,利用的就是call改變this實現的,也是物件導向的一種深層次應用

// 需求:需要把類陣列轉換為陣列

// 類陣列:具備和陣列類似的結構(索引和length以及具備interator可迭代性),但是並不是陣列的例項(不能用陣列原型上的方法),我們把這樣的結構稱為類陣列結構

function func()

console.

log(args)

;// 4.arguments具備和陣列類似的結構,所以運算元組的一些**(例如:迴圈)也同樣適用於arguments;如果我們讓array原型上的內建方法執行,並且讓方法中的this變為我們要操作的類陣列,那麼就相當於我們在「借用陣列原型上的方法操作類陣列」,讓類陣列也和陣列一樣可以呼叫這些方法實現具體的需求

let args = array.prototype.slice.

call

(arguments)

;let args =

.slice.

call

(arguments)

; console.

log(args)

;

[

].foreach.

call

(arguments, item =>

);

// func(10, 20, 30, 40);

array.prototype.slice array原型上slice實現原理

array.prototype.

slice

=function

slice()

return args;};

let arr =[10

,20,30

];console.

log(arr.

slice()

);

// 核心原理:給context設定乙個屬性(屬性名盡可能保持唯一,避免我們自己設定的屬性修改預設物件中的結構,例如可以基於symbol實現,也可以建立乙個時間戳名字),屬性值一定是我們要執行的函式(也就是this,call中的this就是我們要操作的這個函式);接下來基於context.***()成員訪問執行方法,就可以把函式執行,並且改變裡面的this(還可以把params中的資訊傳遞給這個函式即可);都處理完了,別忘記把給context設定的這個屬性刪除掉(人家之前沒有你自己加,加完了我們需要把它刪了)

// 如果context是基本型別值,預設是不能設定屬性的,此時我們需要把這個基本型別值修改為它對應的引用型別值(也就是建構函式的結果)

function.prototype.

call

=function

call

(context,

...params)

else

}let key =

symbol

('key'),

result;

context[key]

=this

; result = context[key]

(...params)

;delete context[key]

;return result;

};

let obj =

;function

func

(x, y)

console.

log(func.

call

(obj,10,

20));

思路:

// // 只要按照成員訪問這種方式執行,就可以讓func中的this變為obj【前提obj中需要有func這個屬性】,當然屬性名不一定是func,只要屬性值是這個函式即可

//obj.$$*** = func;

//obj.$$***(10,20);

// 建立乙個值的兩種方法:對於引用資料型別來講,兩種方式沒啥區別,但是對於值型別,字面量方式建立的是基本型別值,但是建構函式方式創造的是物件型別值;再但是,不管基本型別還是物件型別都是所屬類的例項,都可以呼叫原型上的方法;(基本值無法給其設定屬性,但是引用值是可以設定屬性的)

// // 1.字面量建立

// let num1 = 10;

// let obj1 = {};

// new num1.constructor(num1);

// // 2.建構函式建立

);//不輸出

js中call和apply的實現原理

實現call的思路 還有就是call方法是放在function prototype上的也就是建構函式才有的call方法 我門可以檢視自己的方法的原型鏈上的也就是 方法名.proto function.prototype 自己定義的建構函式通過原型鏈可以找到原型 function.prototype中...

ret和call的原理

1.ret 指令用棧中的資料,修改ip的內容,從而實現近轉移 cpu執行ret指令時,進行下面兩步操作 1 ip ss 16 sp 使用棧頂元素修改ip實現跳轉 2 sp sp 2 2.retf 用棧中的資料,修改cs和ip的內容,從而實現遠轉移 cpu執行retf指令時,進行下面四步操作 1 ip...

關於call的使用和原理分析

call 方法使用乙個指定的this值和單獨給出的乙個或多個引數來呼叫乙個函式。var obj window.a 100var b obj.b b 100 b.call obj 1 function.call thisarg,arg1,arg2,thisarg 可選的。在 function 函式執行...