摘要:系統(tǒng),扎實(shí)的語(yǔ)言基礎(chǔ)是一個(gè)優(yōu)秀的前端工程師必須具備的。第一個(gè)參數(shù)為調(diào)用函數(shù)時(shí)的指向,隨后的參數(shù)則作為函數(shù)的參數(shù)并調(diào)用,也就是。和的區(qū)別只有一個(gè),就是它只有兩個(gè)參數(shù),而且第二個(gè)參數(shù)為調(diào)用函數(shù)時(shí)的參數(shù)構(gòu)成的數(shù)組。
系統(tǒng),扎實(shí)的 javascript 語(yǔ)言基礎(chǔ)是一個(gè)優(yōu)秀的前端工程師必須具備的。在看了一些關(guān)于 call,apply,bind 的文章后,我還是打算寫下這篇總結(jié),原因其實(shí)有好幾個(gè)。首先,在如今 ES6 大行其道的今天,很多文章中講述的它們的應(yīng)用場(chǎng)景其實(shí)用 ES6 可以更優(yōu)雅的解決。再則,講它們的實(shí)現(xiàn)原理的文章不多,本文將把它們通過代碼一一模擬實(shí)現(xiàn),讓它們不再神秘。不謙虛的說,關(guān)于 call,apply,bind 的知識(shí),看這一篇文章就夠了。
改變函數(shù)中 this 指向的三兄弟我們知道在 javascript 的 function 中有 this,arguments 等關(guān)鍵字。本文不討論 this 指向問題,那個(gè)都可以多帶帶整一篇文章了。一個(gè)常見的使用場(chǎng)景是當(dāng)你使用 . 來調(diào)用一個(gè)函數(shù)的時(shí)候,此時(shí)函數(shù)中 this 指向 . 前面的調(diào)用者:
const person = { name: "YuTengjing", age: 22, introduce() { console.log(`Hello everyone! My name is ${this.name}. I"m ${this.age} years old.`); } }; // this 此時(shí)指向 person console.log(person.introduce()); // => Hello everyone! My name is YuTengjing. I"m 22 years old.?
通過 call,apply,bind 這三兄弟可以改變 introduce 中 this 的指向。
callconst myFriend = { name: "dongdong", age: 21, }; console.log(person.introduce.call(myFriend)); // => Hello everyone! My name is dongdong. I"m 21 years old.?
通過上面代碼我們可以看出 introduce 這個(gè)函數(shù)中的 this 指向被改成了 myFriend。Function.prototype.call 的函數(shù)簽名是 fun.call(thisArg, arg1, arg2, ...)。第一個(gè)參數(shù)為調(diào)用函數(shù)時(shí) this 的指向,隨后的參數(shù)則作為函數(shù)的參數(shù)并調(diào)用,也就是 fn(arg1, arg2, ...)。
applyapply 和 call 的區(qū)別只有一個(gè),就是它只有兩個(gè)參數(shù),而且第二個(gè)參數(shù)為調(diào)用函數(shù)時(shí)的參數(shù)構(gòu)成的數(shù)組。函數(shù)簽名:func.apply(thisArg, [argsArray])。如果不用給函數(shù)傳參數(shù),那么他倆就其實(shí)是完全一樣的,需要傳參數(shù)的時(shí)候注意它的應(yīng)該將參數(shù)轉(zhuǎn)換成數(shù)組形式。
一個(gè)簡(jiǎn)單的例子:
function displayHobbies(...hobbies) { console.log(`${this.name} likes ${hobbies.join(", ")}.`); } // 下面兩個(gè)等價(jià) displayHobbies.call({ name: "Bob" }, "swimming", "basketball", "anime"); // => // => Bob likes swimming, basketball, anime.? displayHobbies.apply({ name: "Bob" }, ["swimming", "basketball", "anime"]); // => Bob likes swimming, basketball, anime.?
有些 API 比如 Math.max 它的參數(shù)為多參數(shù),當(dāng)我們有多參數(shù)構(gòu)成的數(shù)組使或者說參數(shù)很多時(shí)該怎么辦呢?
// Math.max 參數(shù)為多參數(shù) console.log(Math.max(1, 2, 3)); // => 3 // 現(xiàn)在已知一個(gè)很大的元素為隨機(jī)大小的整數(shù)數(shù)組 const bigRandomArray = [...Array(10000).keys()].map(num => Math.trunc(num * Math.random())); // 怎樣使用 Math.max 獲取 bigRandomArray 中的最大值呢?Math.max 接受的是多參數(shù)而不是數(shù)組參數(shù)啊! // 思考下面的寫法 console.log(Math.max.apply(null, bigRandomArray)); // => 9936
可以上 ES6 的話就簡(jiǎn)單了,使用擴(kuò)展運(yùn)算符即可,優(yōu)雅簡(jiǎn)潔。
console.log(Math.max(...bigRandomArray));bind
bind 和上面兩個(gè)用途差別還是比較大,如同字面意思(綁定),是用來綁定 this 指向的,返回一個(gè)原函數(shù)被綁定 this 后的新函數(shù)。一個(gè)簡(jiǎn)單的例子:
const person = { name: "YuTengjing", age: 22, }; function introduce() { console.log(`Hello everyone! My name is ${this.name}. I"m ${this.age} years old.`); } const myFriend = { name: "dongdong", age: 21 }; person.introduce = introduce.bind(myFriend); // person.introduce 的 this 已經(jīng)被綁定到 myFriend 上了 console.log(person.introduce()); // => Hello everyone! My name is dongdong. I"m 21 years old. console.log(person.introduce.call(person)); // => Hello everyone! My name is dongdong. I"m 21 years old.?
bind 的函數(shù)簽名是 func.bind(thisArg, arg1, arg2, ...)。春招的時(shí)候被問過 bind 的第二個(gè)參數(shù)是干嘛用的,因?yàn)槲抑皩懘a本身不怎么用這幾個(gè) API,用的時(shí)候我也只用第一個(gè)參數(shù),所以當(dāng)時(shí)面試的時(shí)候被問這個(gè)問題的時(shí)候我還是愣了一下。不過其實(shí)如果可以傳多個(gè)參數(shù)的話,猜也能猜得出來是干嘛用的,我當(dāng)時(shí)就猜對(duì)了φ(* ̄0 ̄)。
學(xué)以致用我們學(xué)習(xí)知識(shí)的時(shí)候不能只是停留在理解層面,需要去思考它們有什么用,應(yīng)用場(chǎng)景有哪些。這樣的話,當(dāng)你處在這種場(chǎng)景中,你就能很自然的想出解決方案。
多參函數(shù)轉(zhuǎn)換為單個(gè)數(shù)組參數(shù)調(diào)用javascript 中有很多 API 是接受多個(gè)參數(shù)的比如之前提過的 Math.max,還有很多例如 Math.min,Array.prototype.push 等它們都是接受多個(gè)參數(shù)的 API,但是有時(shí)候我們只有多個(gè)參數(shù)構(gòu)成的數(shù)組,而且可能還特別大,這個(gè)時(shí)候就可以利用 apply 巧妙的來轉(zhuǎn)換。
下面是利用 apply 來巧妙的合并數(shù)組:
let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; Array.prototype.push.apply(arr1, arr2); console.log(arr1); // [1, 2, 3, 4, 5, 6]
但是,其實(shí)用 ES6 可以非常的簡(jiǎn)潔:
arr1.push(...arr2);
所以,忘了這種用法吧( ̄︶ ̄)↗ 。
將類數(shù)組轉(zhuǎn)換為數(shù)組JavaScript類型化數(shù)組是一種類似數(shù)組的對(duì)象,它們有數(shù)組的一些屬性,但是如果你用 Array.isArray() 去測(cè)試會(huì)返回 false,常見的像 arguments,NodeList 等。
function testArrayLike() { // 有 length 屬性沒有 slice 屬性 console.log(arguments.length); // => 3 console.log(arguments.slice); // => undefined // 類數(shù)組不是數(shù)組 console.log(Array.isArray(arguments)); // => false console.log(arguments); // => { [Iterator] 0: "a", 1: "b", 2: "c", [Symbol(Symbol.iterator)]: [λ: values] }? const array = Array.prototype.slice.call(arguments); console.log(Array.isArray(array)); // => true console.log(array); // => [ "a", "b", "c" ] } testArrayLike("a", "b", "c");
其實(shí) 把 slice 換成 concat,splice 等其它 API 也是可以的。思考:為什么通過 Array.prototype.slice.call(arrayLike) 可以轉(zhuǎn)換類數(shù)組為數(shù)組?
我沒有研究過 slice 的具體實(shí)現(xiàn),猜測(cè)是下面這樣的:
Array.prototype.mySlice = function(start=0, end) { const array = this; const end = end === undefined ? array.length : end; const resultArray = []; if (array.length === 0) return resultArray; for (let index = start; index < end; index++) { resultArray.push(array[index]); } return resultArray; }
我想 slice 內(nèi)部實(shí)現(xiàn)可能就是會(huì)像我上面的代碼一樣只需要一個(gè) length 屬性,遍歷元素返回新數(shù)組,所以調(diào)用 slice 時(shí)將其 this 指向類數(shù)組能正常工作。
其實(shí),這個(gè)用法也可以忘了,用 ES6 來轉(zhuǎn)換不造多簡(jiǎn)單,ES6 大法好
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/105146.html
摘要:出現(xiàn)箭頭函數(shù)的時(shí)候,指向?yàn)槎x時(shí)的上下文對(duì)象而非指向時(shí),并且不能被改變首先我們先看一個(gè)例子由上面的例子我們可以看出來此時(shí)指針在用改變了之后指向的依然是全局對(duì)象非嚴(yán)格瀏覽器環(huán)境中是而非。 javascript基礎(chǔ)之this指針 越往后面學(xué)越發(fā)現(xiàn)基礎(chǔ)的重要性,所以打算重新過一遍基礎(chǔ),之后出幾個(gè)vue和react的實(shí)戰(zhàn)教程。ok,嚴(yán)歸正傳。 首先什么是this this是執(zhí)行上下文創(chuàng)建時(shí)確定...
摘要:參考鏈接在中,和是對(duì)象自帶的三個(gè)方法,都是為了改變函數(shù)體內(nèi)部的指向。返回值是函數(shù)方法不會(huì)立即執(zhí)行,而是返回一個(gè)改變了上下文后的函數(shù)。而原函數(shù)中的并沒有被改變,依舊指向全局對(duì)象。原因是,在中,多次是無(wú)效的。 參考鏈接:https://juejin.im/post/59bfe8... 在JavaScript中,call、apply和bind是Function對(duì)象自帶的三個(gè)方法,都是為了改變...
摘要:文章盡量使用大量實(shí)例進(jìn)行講解,它們的使用場(chǎng)景。在嚴(yán)格模式下,函數(shù)被調(diào)用后,里面的默認(rèn)是后面通過調(diào)用函數(shù)上的和方法,該變指向,函數(shù)里面的指向。利用,可以傳入外層的上下文。同樣適用的還有,里面的對(duì)象,它也是一種類數(shù)組對(duì)象。 call,apply and bind in JavaScript 在ECMAScript中,每個(gè)函數(shù)都包含兩個(gè)繼承而來的方法:apply() 和 call(),這兩個(gè)...
摘要:也就是說當(dāng)返回的函數(shù)作為構(gòu)造函數(shù)的時(shí)候,時(shí)指定的值會(huì)失效,但傳入的參數(shù)依然生效。構(gòu)造函數(shù)效果的優(yōu)化實(shí)現(xiàn)但是在這個(gè)寫法中,我們直接將,我們直接修改的時(shí)候,也會(huì)直接修改函數(shù)的。 JavaScript深入系列第十一篇,通過bind函數(shù)的模擬實(shí)現(xiàn),帶大家真正了解bind的特性 bind 一句話介紹 bind: bind() 方法會(huì)創(chuàng)建一個(gè)新函數(shù)。當(dāng)這個(gè)新函數(shù)被調(diào)用時(shí),bind() 的第一個(gè)參數(shù)...
摘要:模擬和模擬一樣,現(xiàn)摘抄下面的代碼添加一個(gè)返回值對(duì)象然后我們定義一個(gè)函數(shù),如果執(zhí)行下面的代碼能夠返回和函數(shù)一樣的值,就達(dá)到我們的目的。 原文:https://zhehuaxuan.github.io/... 作者:zhehuaxuan 目的 本文主要用于理解和掌握call,apply和bind的使用和原理,本文適用于對(duì)它們的用法不是很熟悉,或者想搞清楚它們?cè)淼耐? 好,那我們開始...
閱讀 2108·2021-11-11 16:55
閱讀 3178·2021-10-11 10:58
閱讀 3052·2021-09-13 10:28
閱讀 3982·2021-07-26 23:57
閱讀 1031·2019-08-30 15:56
閱讀 1339·2019-08-29 13:15
閱讀 1275·2019-08-26 18:18
閱讀 1278·2019-08-26 13:44