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