下面我們來看乙個例子
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 函式執行...