如何理解js中的call和apply?

大家好,我是IT修真院萌新分院第3期的學(xué)員張曉琳,一枚正直、純潔、善良的前端程序員今天給大家分享一下,修真院官網(wǎng)js任務(wù)2深度思考中的知識(shí)點(diǎn)——如何理解js中call和apply?

1.背景介紹

call 和 apply 都是為了改變某個(gè)函數(shù)運(yùn)行時(shí)的?

context 即上下文而存在的,換句話說(shuō),

就是為了改變函數(shù)體內(nèi)部 this 的指向。

因?yàn)?JavaScript 的函數(shù)存在

「定義時(shí)上下文」和「運(yùn)行時(shí)上下文」

以及「上下文是可以改變的」這樣的概念。

2.知識(shí)剖析

1. apply:?

方法能劫持另外一個(gè)對(duì)象的方法,繼承另外一個(gè)對(duì)象的屬性.?

Function.apply(obj,args)方法能接收兩個(gè)參數(shù)

obj:這個(gè)對(duì)象將代替Function類(lèi)里this對(duì)象

args:這個(gè)是數(shù)組,它將作為參數(shù)傳給Function(args-->arguments)

2. call?

和apply的意思一樣,只不過(guò)是參數(shù)列表不一樣

Function.call(obj,[param1[,param2[,…[,paramN] ] ] ] )

obj:這個(gè)對(duì)象將代替Function類(lèi)里this對(duì)象

params:這個(gè)是一個(gè)參數(shù)列表

3.常見(jiàn)問(wèn)題

如何使用call和apply?

4.解決方案

call 和 apply 的作用基本類(lèi)似,?

都是去執(zhí)行function并將這個(gè)function?

的context替換成第一個(gè)參數(shù)帶入。?

兩者的不同是call 必須將function 的參數(shù)一一帶入,接受的是連續(xù)參數(shù)

而 apply 接受的是數(shù)組參數(shù) 只要在第二個(gè)參數(shù)帶入一個(gè)數(shù)列。

//控制臺(tái)運(yùn)行:

//j? k? 形參

function add(j, k) {

? ? return j + k;

}

function sub(j, k) {

? ? return j - k;

}

// 5 3? 實(shí)參

add(5, 3); //8

add.call(sub, 5, 3); //8

add.apply(sub, [5, 3]); //8

sub(5, 3); //2

sub.call(add, 5, 3); //2

sub.apply(add, [5, 3]); //2

//通過(guò)call和apply實(shí)現(xiàn)對(duì)象繼承。

var Parent = function () {

? ? this.name = "yjc";

? ? this.age = 22;

}

var child = {};

console.log(child);//Object {} ,空對(duì)象

Parent.call(child);

console.log(child); //Object {name: "yjc", age: 22}

//call方法1

window.color = 'red';

document.color = 'yellow';

var s1 = {color: 'blue' };

function changeColor(){

? ? console.log(this.color);

}

//2

changeColor.call();? ? ? ? //red (默認(rèn)傳遞參數(shù))

changeColor.call(window);? //red

changeColor.call(document); //yellow

changeColor.call(this);? ? //red

changeColor.call(s1);? ? ? //blue

var Pet = {

? ? words : '...',

? ? speak : function (say) {

? ? ? ? console.log(say + ''+ this.words)

}

}

Pet.speak('Speak'); // 結(jié)果:Speak...

var Dog = {

? ? words:'Wang'

}

//將this的指向改變成了Dog

Pet.speak.call(Dog, 'Speak'); //結(jié)果:SpeakWang

//apply方法1

window.number = 'one';

document.number = 'two';

var s1 = {number: 'three' };

function changeColor(){

? ? console.log(this.number);

}

changeColor.apply();? ? ? ? //one (默認(rèn)傳參)

changeColor.apply(window);? //one

changeColor.apply(document); //two

changeColor.apply(this);? ? //one

changeColor.apply(s1);? ? ? //three

//方法2

function Pet(words){

? ? this.words = words;

? ? this.speak = function () {

? ? ? ? console.log( this.words)

}

}

function Dog(words){

? ? //Pet.call(this, words); //結(jié)果:Wang

? ? Pet.apply(this, arguments); //結(jié)果:Wang

}

var dog = new Dog('Wang');

dog.speak();

5.編碼實(shí)戰(zhàn)

// call方法可以用來(lái)代替另一個(gè)對(duì)象調(diào)用一個(gè)方法,

// call方法可以將一個(gè)函數(shù)的對(duì)象上下文從初始的上下文改變?yōu)閠hisObj指定的新對(duì)象,

// 如果沒(méi)有提供thisObj參數(shù),那么Global對(duì)象被用于thisObj。

//1:

? ? function add(c,d){

? ? ? ? return this.a + this.b + c + d;

}

var s = {a:1, b:2};

console.log(add.call(s,3,4)); // 1+2+3+4 = 10

console.log(add.apply(s,[5,6])); // 1+2+5+6 = 14

//2:

window.firstName = "Cynthia";

window.lastName = "_xie";

var myObject = {firstName:'my', lastName:'Object'};

function getName(){

? ? console.log(this.firstName + this.lastName);

}

function getMessage(sex,age){

? ? console.log(this.firstName + this.lastName + " 性別: " + sex + " age: " + age );

}

getName.call(window); // Cynthia_xie

getName.call(myObject); // myObject

getName.apply(window); // Cynthia_xie

getName.apply(myObject);// myObject

getMessage.call(window,"女",21); //Cynthia_xie 性別: 女a(chǎn)ge: 21

getMessage.apply(window,["女",21]); // Cynthia_xie 性別: 女a(chǎn)ge: 21

getMessage.call(myObject,"未知",22); //myObject 性別: 未知age: 22

getMessage.apply(myObject,["未知",22]); // myObject 性別: 未知 age: 22

6.擴(kuò)展思考

call()和apply()兩種方法的區(qū)別??

相同點(diǎn):兩個(gè)方法產(chǎn)生的作用是完全一樣的

不同點(diǎn):方法傳遞的參數(shù)不同

call()接受的是一個(gè)參數(shù)列表,而apply()接受一個(gè)參數(shù)數(shù)組。

func.call(this, arg1, arg2);

func.apply(this, [arg1, arg2])

其中 this 是你想指定的上下文,他可以是任何一個(gè) JavaScript 對(duì)象(JavaScript 中一切皆對(duì)象),

call 需要把參數(shù)按順序傳遞進(jìn)去,而 apply 則是把參數(shù)放在數(shù)組里。

因此要說(shuō)適用條件的話,當(dāng)你的參數(shù)是明確知道數(shù)量時(shí)用 call 。

而不確定的時(shí)候用 apply,然后把參數(shù) push 進(jìn)數(shù)組傳遞進(jìn)去。

7.參考文獻(xiàn)

參考

8.更多討論

問(wèn)題:

Q1:王姣妍:是call還是apply能改變this的指向?

A1:張曉琳:兩個(gè)都能改,就是傳參數(shù)方式不一樣呀,apply傳數(shù)組,call傳字符串。

Q2:王棟:apply的應(yīng)用場(chǎng)景呢??

A2:其他人:

我首先從網(wǎng)上查到關(guān)于apply和call的定義,然后用示例來(lái)解釋這兩個(gè)方法的意思和如何去用.??

?????????apply:方法能劫持另外一個(gè)對(duì)象的方法,繼承另外一個(gè)對(duì)象的屬性.??

?Function.apply(obj,args)方法能接收兩個(gè)參數(shù)??

obj:這個(gè)對(duì)象將代替Function類(lèi)里this對(duì)象??

args:這個(gè)是數(shù)組,它將作為參數(shù)傳給Function(args-->arguments)??

?????????call:和apply的意思一樣,只不過(guò)是參數(shù)列表不一樣.??

?Function.call(obj,[param1[,param2[,…[,paramN]]]])??

obj:這個(gè)對(duì)象將代替Function類(lèi)里this對(duì)象??

params:這個(gè)是一個(gè)參數(shù)列表??

1.apply示例:??

/*定義一個(gè)人類(lèi)*/???

function?Person(name,age)?{???

this.name=name;?this.age=age;???

}???

/*定義一個(gè)學(xué)生類(lèi)*/???

functionStudent(name,age,grade)?{???

Person.apply(this,arguments);?this.grade=grade;???

}???

//創(chuàng)建一個(gè)學(xué)生類(lèi)???

var?student=new?Student("qian",21,"一年級(jí)");???

//測(cè)試???

alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);???

//大家可以看到測(cè)試結(jié)果name:qian?age:21?grade:一年級(jí)???

//學(xué)生類(lèi)里面我沒(méi)有給name和age屬性賦值啊,為什么又存在這兩個(gè)屬性的值呢,這個(gè)就是apply的神奇之處.? ?

分析:?Person.apply(this,arguments);??

this:在創(chuàng)建對(duì)象在這個(gè)時(shí)候代表的是student??

arguments:是一個(gè)數(shù)組,也就是[“qian”,”21”,”一年級(jí)”];??

也就是通俗一點(diǎn)講就是:用student去執(zhí)行Person這個(gè)類(lèi)里面的內(nèi)容,在Person這個(gè)類(lèi)里面存在this.name等之類(lèi)的語(yǔ)句,這樣就將屬性創(chuàng)建到了student對(duì)象里面?

Q3:王棟:call的應(yīng)用場(chǎng)景呢??

A3:其他人:在給對(duì)象參數(shù)的情況下,如果參數(shù)的形式是數(shù)組的時(shí)候,比如apply示例里面?zhèn)鬟f了參數(shù)arguments,這個(gè)參數(shù)是數(shù)組類(lèi)型,并且在調(diào)用Person的時(shí)候參數(shù)的列表是對(duì)應(yīng)一致的(也就是Person和Student的參數(shù)列表前兩位是一致的)?就可以采用?apply?,?如果我的Person的參數(shù)列表是這樣的(age,name),而Student的參數(shù)列表是(name,age,grade),這樣就可以用call來(lái)實(shí)現(xiàn)了,也就是直接指定參數(shù)列表對(duì)應(yīng)值的位置(Person.call(this,age,name,grade));?

PPT

如何理解js中call和apply視頻


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

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

  • 大家好,我是IT修真院深圳分院第01期學(xué)員,一枚正直純潔善良的web程序員。 今天給大家分享一下,修真院官網(wǎng)JS任...
    嘴角那抹溫柔閱讀 410評(píng)論 0 0
  • 1.背景介紹 call和apply都是為了改變某個(gè)函數(shù)運(yùn)行時(shí)的context即上下文而存在的,換句話說(shuō),就是為了改...
    遠(yuǎn)望的云閱讀 643評(píng)論 0 1
  • 工廠模式類(lèi)似于現(xiàn)實(shí)生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情,實(shí)現(xiàn)同樣的效果;這時(shí)候需要使用工廠模式。簡(jiǎn)單...
    舟漁行舟閱讀 8,116評(píng)論 2 17
  • 單例模式 適用場(chǎng)景:可能會(huì)在場(chǎng)景中使用到對(duì)象,但只有一個(gè)實(shí)例,加載時(shí)并不主動(dòng)創(chuàng)建,需要時(shí)才創(chuàng)建 最常見(jiàn)的單例模式,...
    Obeing閱讀 2,313評(píng)論 1 10
  • 晚上番茄籽在隔壁鄰居家玩,旁邊兩個(gè)姐姐在下跳棋,這是小家伙第一次見(jiàn)這玩意兒,我就問(wèn)他:“姐姐在做什么呀?”因?yàn)檎娴?..
    沙格西矛閱讀 267評(píng)論 0 0

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