摘要:和概覽我們要將歸為一類,多帶帶歸為一類三者的共同點是都可以指定和都是綁定在的原型上的,所以的實例都可以調用這三個方法至于為什么,看完這篇文章你就懂了如果你不懂什么是實例的話,請移步深入淺出面向對象和原型概念篇深入淺出面向對象和原型概念篇第一個
1.call/apply和bind概覽
我們要將call/apply歸為一類,bind多帶帶歸為一類
三者的共同點是都可以指定this
call/apply和bind都是綁定在Function的原型上的,所以Function的實例都可以調用這三個方法
Function.prototype.call(this,arg1,arg2) Function.prototype.apply(this,[arg1,arg2]) Function.prototype.bind(this,arg1,arg2)
至于為什么,看完這篇文章你就懂了:)
如果你不懂什么是實例的話,請移步深入淺出面向對象和原型【概念篇1】、深入淺出面向對象和原型【概念篇2】2. call / apply —— 第一個參數是this(上下文) 2.1 作用和返回值
作用
調用函數
改變該函數this值
操作參數
返回值
返回值是你調用的方法的返回值,若該方法沒有返回值,則返回undefined。
window.a = 1 function print(b, c) { console.log(this.a, b, c) } print(2, 3) // 1 2 3 print.call({a: -1}, -2, -3) // -1 -2 -3 print.apply({a: 0}, [-2, -3]) // 0 -2 -3
call()方法的作用和 apply() 方法是一樣的,只有一個區別
call()方法接受的是若干個參數
apply()方法接受的是一個包含若干個參數的數組
// 例子一 // Math.max()不接收數組的傳遞,我們可以使用apply方法 let answer = Math.max.apply(null, [2, 4, 3]) console.log(answer) // 4 // 注意下面三個等價 Math.max.apply(null, [2, 4, 3]) Math.max.call(null, 2, 4, 3) Math.max(2, 4, 3)
// 例子二 // 合并兩個數組 let arr1 = ["parsnip", "potato"] let arr2 = ["celery", "beetroot"] // 將第二個數組融合進第一個數組 // 相當于 arr1.push("celery", "beetroot"); Array.prototype.push.apply(arr1, arr2) // 注意?。?!this的意思是誰調用了push這個方法 // 所以當 this = arr1 后 // 就成了 arr1 調用了 push方法 // 所以上述表達式等價于 arr1.push("celery", "beetroot") console.log(arr1) // ["parsnip", "potato", "celery", "beetroot"]
例子二中非常值得注意的就是arr2數組被拆開了,成了一個一個的參數
所以,apply經常性的作用之一就是將數組元素迭代為函數參數
// 例子三 Math.max.apply(null, [2, 4, 3]) // 完美運行 arr1.push.apply(null, arr2) // 報錯 Uncaught TypeError: Array.prototype.push called on null or undefined // 說明 Math = { max: function (values) { // 沒用到this值 } } Array.prototype.push = function (items) { // this -> 調用push方法的數組本身 // this為null的話,就是向null里push // Array.prototype.push called on null or undefined } // 下面三個值是完全等價的,因為this值已經是arr1 Array.prototype.push.apply(arr1, arr2) arr1.push.apply(arr1, arr2) arr2.push.apply(arr1, arr2)2.3 小測試
function xx() { console.log(this) } xx.call("1") // ?? xx() // ??
如果答案和你想的不一樣,請移步this總結【1】—— this概覽3.bind
fun.bind(thisArg[, arg1[, arg2[, ...]]])3.1作用
改變this
返回一個新函數
3.2 綁定函數、目標函數實例使用bind()方法后會返回一個新的函數【綁定函數】
而原函數為【目標函數】
我個人更喜歡用新函數和原函數來區分,因為新名詞越多,理解上的困難越大
那么新函數被調用時會發生什么呢?
下面一句話務必記住
其實就是把原函數call/apply一下,并指定你傳遞的this
function xx() { console.log(this) } let foo = xx.bind({"name":"jason"}) // foo —— 新函數【綁定函數】 // xx —— 原函數【目標函數】 foo() // 新函數調用時對原函數的操作 // 下面是偽代碼 // function foo(){ // xx.call({"name":"jason"}) // } // 1.給xx(原函數)指定this 2.調用xx(原函數) // 一定要注意這兩步是在新函數被調用時才發生,不調用不發生 // 你也可以總結為一句話,給原函數 call/apply 了一下3.3 bind()傳參和新函數【綁定函數】傳參
bind(this,arg1)會將arg1插入到原函數【目標函數】的參數列表的開始位置
傳遞給新函數【綁定函數】的參數會跟在它們的后面
function list() { // 原函數【目標函數】 return Array.prototype.slice.call(arguments); } let listTest = list(1, 2, 3); // [1, 2, 3] // 新函數【綁定函數】 let leadingThirtysevenList = list.bind(undefined, 37); let list1 = leadingThirtysevenList(); // [37] let list2 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]3.3 原生實現一個bind,使用 this + call/apply【重點】
思考過程
// 實現bind其實就是實現bind的特點 // 1.bind的第一個參數是this // 2.bind可以return一個新函數,這個新函數可以調用原函數并且可以指定其this,還可以接受參數 // 3.bind返回的新函數傳遞的參數要在bind傳遞的參數的后面
代碼
Function.prototype._bind = function () { // 聲明bind接受的參數【除去this】為bindArgs // 因為第一個參數是this,需要去掉 let bindArgs = Array.prototype.slice.call(arguments, 1) let bindThis = arguments[1] // 聲明原函數【目標函數】為targetObj let targetObj = this return function () { // return出來的的函數接受的參數為newArgs // 要在return出來的新函數里把bindArgs和newArgs合并,使用數組的concat方法 let newArgs = Array.prototype.slice.call(arguments) return targetObj.apply(bindThis, bindArgs.concat(newArgs)) } }4. 既然都是指定this,為什么已經有call/apply,又要有bind呢? 4.1 你從未關注過函數的返回值
你在控制臺輸入console.log(1)為什么一個是1,一個是undefined?
1是執行console.log()方法的輸出值,undefined是這個方法的返回值 所以,你要知道所有的函數都有返回值,一定要去關注一下函數的返回值4.2 call/apply 與 bind 的返回值
xxx.call()/xxx.apply() 的返回值是由xxx本身的返回值決定的 xxx.bind() 的返回值是一個函數
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107619.html
摘要:首先介紹一下和的定義和的作用是改變函數運行時的上下文環境改變的指向將綁定到或者說調用了里面的方法。方法返回的是修改過后的函數追夢子追夢子執行成功 這是一道今天遇到的面試題 showImg(https://segmentfault.com/img/bV8lco?w=330&h=222); 因為setTimeout屬于匿名函數,this指向window,所以this.id = 1但還是先總...
總結call,apply,bind方法的理解使用和區別。 call,apply,bind這三個方法在JavaScript中是用來改變函數調用的this指向。那么改變函數this指向有什么用呢?我們先來看一段代碼 var a= { name:harden, fn:function () { console.log(this.name); } } var b =...
摘要:關于前端中是個老生常談的問題,總是說不清道不明,看這里。的大致用法,相信接觸過前端的同學都知道,無非以下種。先想一下,兩次執行后結果是什么。輸出總結被誰調用指向誰,沒有被調用的情況下,瀏覽器默認為。由于箭頭函數中的,總是指向父級作用域。 關于this 前端中this是個老生常談的問題,總是說不清道不明,看這里。this只能用在函數里面,相信全世界的人都知道。this就是函數在被執行的時...
摘要:和區別其實他們的作用是一樣的,只是傳遞的參數不一樣而已。接受個參數,第一個參數指定了函數體內對象的指向,第二個參數為數組或者一個類數組??磦€栗子一個有意思的事在中,多次是無效的。而則會立即執行函數。 背景 前兩天在做小程序的需求的時候用到bind的時候才想起自己對這三的東西的了解比較淺薄,這個時候用的時候就有點怕。時候還是要好好學習下,理解下怎么玩。 正文 先說call 和 apply...
摘要:如果連續呢結果會是什么結果還是第一個原因是,在中,多次是無效的。更深層次的原因,的實現,相當于使用函數在內部包了一個,第二次相當于再包住第一次故第二次以后的是無法生效的。 this 1.其實js中的this沒那么難理解,當找不到this時記住一句話:誰調我,我就指誰!new 誰指誰 function text1(){ console.log(this); //指wind...
閱讀 3724·2021-10-13 09:39
閱讀 3789·2021-09-24 09:48
閱讀 1189·2021-09-01 10:30
閱讀 2526·2019-08-30 15:55
閱讀 1774·2019-08-29 16:39
閱讀 2296·2019-08-26 13:55
閱讀 3050·2019-08-26 12:23
閱讀 1634·2019-08-26 11:59