理解js的 call(),apply(),bind()和模擬實現(xiàn)call(),apply(),bind()

1,

首先call()、apply()、bind() 都是用來重定義 this 這個對象的

例子1:


<!DOCTYPE html>

<html lang="en">

<head>

? ? <meta charset="UTF-8">

? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">

? ? <meta http-equiv="X-UA-Compatible" content="ie=edge">

? ? <title>call</title>

</head>

<body>


</body>

<script>

? ? var name="蓋倫";

? ? var sex="男";

? ? var character={

? ? ? ? name: "艾希",

? ? ? ? character_sex: "女",

? ? ? ? say:function(){

? ? ? ? ? ? console.log(this.name + " "+ this.sex)

? ? ? ? }

? ? }

? ? console.log(character.name)

? ? character.say();

</script>

</html>


結果:

1

如果把say里面的console.log改以下

console.log(this.name + " "+ this.character_sex)

結果:

2

這樣的結果是因為this的指向問題,say里面this的指向是character這個對象,然后character.里沒有定義sex。call和apply()、bind()都可改變this指向

列子:


<!DOCTYPE html>

<html lang="en">

<head>

? ? <meta charset="UTF-8">

? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">

? ? <meta http-equiv="X-UA-Compatible" content="ie=edge">

? ? <title>call</title>

</head>

<body>


</body>

<script>

? ? var gailun={

? ? ? ? name:"蓋倫",

? ? ? ? sex:"男"

? ? }

? ? var character={

? ? ? ? name: "艾希",

? ? ? ? character_sex: "女",

? ? ? ? say:function(){

? ? ? ? ? ? console.log(this.name + " "+ this.sex)

? ? ? ? }

? ? }

? ? character.say.call(gailun)

</script>

</html>


結果:

通過call()就將原來指向character的this變成指向gailun,bind(),apply(),通用會改變this指向。


3

2,call()和apply()的區(qū)別

call()方法接受的是一個參數(shù)列表,而apply()方法接受的是一個包含多個參數(shù)的數(shù)組。

列子:



<!DOCTYPE html>

<html lang="en">

<head>

? ? <meta charset="UTF-8">

? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">

? ? <meta http-equiv="X-UA-Compatible" content="ie=edge">

? ? <title>call</title>

</head>

<body>


</body>

<script>

? ? var gailun={

? ? ? ? name:"蓋倫",

? ? ? ? sex:"男"

? ? }

? ? var timo={

? ? ? ? name:"提莫",

? ? ? ? sex:"未知"

? ? }

? ? var character={

? ? ? ? name: "艾希",

? ? ? ? character_sex: "女",

? ? ? ? say:function(from){

? ? ? ? ? ? console.log(this.name + " "+ this.sex+" "+"來自"+from)

? ? ? ? }

? ? }

? ? character.say.call(gailun,"德瑪西亞");

? ? character.say.apply(timo,["班德爾城"]);

</script>

</html>


結果:


4

假如apply()參數(shù)不是array類型,會報以下錯誤。

TypeError: second argument to Function.prototype.apply must be an array

假如:character.say.apply(null,["班德爾城"]);這樣寫,那么this指向了window。

我們?nèi)绻趙indow下這樣定義:

?? var name="cc"

? ? var sex ="男"

那么結果應該會這樣:


cc 男 來自班德爾城


3,bind()

bind()方法和call,apply不一樣的地方在于它返回的是一個函數(shù)

列子:


<!DOCTYPE html>

<html lang="en">

<head>

? ? <meta charset="UTF-8">

? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">

? ? <meta http-equiv="X-UA-Compatible" content="ie=edge">

? ? <title>call</title>

</head>

<body>


</body>

<script>

? ? var name="cc"

? ? var sex ="男"

? ? var gailun={

? ? ? ? name:"蓋倫",

? ? ? ? sex:"男"

? ? }

? ? var timo={

? ? ? ? name:"提莫",

? ? ? ? sex:"未知"

? ? }

? ? var character={

? ? ? ? name: "艾希",

? ? ? ? sex: "女",

? ? ? ? say:function(from){

? ? ? ? ? ? console.log(this.name + " "+ this.sex+" "+"來自"+from)

? ? ? ? }

? ? }

? ? character.say.call(gailun,"德瑪西亞");

? ? character.say.apply(timo,["班德爾城"]);

? ? console.log(character.say.bind(gailun,"德瑪西亞"))

</script>

</html>


結果:


5

理解call(),apply(),bind()并不困難,但是面試中許多面試官都會問,“能自己模擬實現(xiàn)這三個函數(shù)嗎?”,生活所迫那么自己實現(xiàn)一下。

參考:https://github.com/mqyqingfeng/Blog/issues/11

實踐寫一個call(),其他參考上面的地址



<!DOCTYPE html>

<html lang="en">

<head>

? ? <meta charset="UTF-8">

? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">

? ? <meta http-equiv="X-UA-Compatible" content="ie=edge">

? ? <title>myCall</title>

</head>

<body>


</body>

<script>

? ? var a=1;

? var bar={

? ? ? a:1

? }

? var bar2={

? ? ? a:2

? }

function testCall(argA,argB){

? return {

? ? ? ? argA:argA,

? ? ? ? argB:argB,

? ? ? ? value:this.a

? }

}

testCall.call(bar,"c","cheng")

Function.prototype.myCall=function(context){

? ? var context = context || window

? ? context.fn=this

? ? let args=[]

? ? for(let i =1;i<arguments.length;i++){

? ? ? ? args.push("arguments["+i+']')

? ? }


? ? var res = eval('context.fn('+args+')')

? ? delete context.fn

? ? return res

}

console.log(testCall.myCall(bar2,"c","cheng"))

console.log(testCall.myCall(null))

</script>

</html>


理解:

首先改變this指向


Function.prototype.call2=function(context) {

????? context.fn=this;context.fn();

????? delete context.fn;

}


如果context為空,則需要把context改成window對象

所以改進一下


Function.prototype.call2=function(context) {

????? var context = context || window;

???? context.fn=this;context.fn();

????? delete context.fn;

}


然后處理參數(shù),



?? let args=[]

? ? for(let i =1;i<arguments.length;i++){

? ? ? ? args.push("arguments["+i+']')

? ? }

???? var res = eval('context.fn('+args+')')


到此完成了 call ()的模擬實現(xiàn)

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些閱讀 2,132評論 0 2
  • 單例模式 適用場景:可能會在場景中使用到對象,但只有一個實例,加載時并不主動創(chuàng)建,需要時才創(chuàng)建 最常見的單例模式,...
    Obeing閱讀 2,311評論 1 10
  • 大家好,我是IT修真院萌新分院第3期的學員張曉琳,一枚正直、純潔、善良的前端程序員今天給大家分享一下,修真院官網(wǎng)j...
    Demon_0481閱讀 640評論 0 2
  • 通過call和apply的模擬實現(xiàn),帶你揭開call和apply改變this的真相 call一句話介紹 call:...
    O8閱讀 331評論 0 1
  • 思想:今天是培訓結束回歸工作的第二天,腦海中培訓的場景還依舊歷歷在目,回想起所學知識,對現(xiàn)在的工作突然有一種豁然開...
    l櫻木花道閱讀 200評論 0 0

友情鏈接更多精彩內(nèi)容