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