日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

深入理解this和call、bind、apply对this的影响及用法

發(fā)布時(shí)間:2023/12/20 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解this和call、bind、apply对this的影响及用法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  首先看一道網(wǎng)易的面試題:

var a = {a:"haha",getA:function(){console.log(this.a);} } var b = {a:"hello"} var getA = a.getA; var getA2 = getA.bind(a); function run(fn){fn(); } //分別輸出 a.getA();//haha getA();//window下面的a對(duì)象 run(a.getA);//window下面的a對(duì)象 getA2.call(b);//haha

  這里考察了三個(gè)點(diǎn):形參實(shí)參的理解、this的指向、call和bind對(duì)this指向的影響。

一、this指向問(wèn)題

  關(guān)于this指向的問(wèn)題,上一篇:理解JavaScript里this關(guān)鍵字有比較好的總結(jié)。

  (1)這里有三種簡(jiǎn)單情況:

  1、如果函數(shù)中的this沒(méi)有調(diào)用它的對(duì)象,那么this指向的就是window(注意:嚴(yán)格模式下這種情況的this會(huì)為空,即undefined

  2、如果函數(shù)中的this被不包含子對(duì)象的對(duì)象所調(diào)用,那么this指向的就是調(diào)用它的對(duì)象。

  3、如果函數(shù)中的this被包含多級(jí)對(duì)象的對(duì)象調(diào)用,this指向的也只是它上一級(jí)的對(duì)象,如下例:

var demoObj = {a:1,b:{fun:function(){console.log(this.a); }} } demoObj.b.fun();//undefined,因?yàn)閠his指向demoObj.b,b里面沒(méi)有a

  這里this不是指向demoObj對(duì)象,而是指向demoObj.b對(duì)象,這里找不到demoObj.b對(duì)象里的a,所以會(huì)輸出undefined。 

  (2)還有三種特殊情況:

  1、還是上面的例子,改一下調(diào)用函數(shù)的方式,如下。

var demoObj = {a:1,b:{fun:function(){console.log(this.a); }} } var newFun = demoObj.b.fun; newFun();//undefined,this指向window

  這里還是得到undefined,但是this的指向卻是window,這里的undefined是因?yàn)闆](méi)找到window對(duì)象里的a,才輸出的undefined。雖然函數(shù)fun是被對(duì)象b所調(diào)用,但是在將fun賦值給變量newFun的時(shí)候并沒(méi)有執(zhí)行,newFun的上級(jí)對(duì)象window,所以最終執(zhí)行時(shí)指向的是window。

  2、構(gòu)造函數(shù)用new實(shí)例對(duì)象時(shí)對(duì)this的影響。

function Fun(){this.name = "haha"; } var stu = new Fun(); console.log(stu.name); //haha

  這里之所以對(duì)象stu.name可以輸出haha,是因?yàn)閚ew關(guān)鍵字就是創(chuàng)建一個(gè)對(duì)象實(shí)例,這個(gè)stu對(duì)象中包含了this.name這個(gè)屬性,相當(dāng)于復(fù)制但卻沒(méi)有執(zhí)行。在執(zhí)行時(shí)調(diào)用這個(gè)函數(shù)Fun的是對(duì)象stu,所以this指向的就是對(duì)象stu。

  用new操作符創(chuàng)建對(duì)象時(shí)發(fā)生的事情:

  第一步: 創(chuàng)建一個(gè)Object對(duì)象實(shí)例。
  第二步: 將構(gòu)造函數(shù)的作用域賦給新對(duì)象(因此this就指向了這個(gè)新對(duì)象)。
  第三步: 執(zhí)行構(gòu)造函數(shù)中的代碼(這里的執(zhí)行并不是真的讓this指向哪里,而是為這個(gè)新對(duì)象添加屬性)。
  第四步: 返回新生成的對(duì)象實(shí)例

  原本的構(gòu)造函數(shù)是window對(duì)象的方法,如果不用new操作符而直接調(diào)用,那么構(gòu)造函數(shù)的執(zhí)行對(duì)象就是window,即this指向了window。現(xiàn)在用new操作符后,this就指向了新生成的對(duì)象。理解這一步至關(guān)重要。

  3、有return的函數(shù)在new時(shí)對(duì)this的影響(正常的構(gòu)造函數(shù)是沒(méi)有return語(yǔ)句),我們先看下面的幾個(gè)例子。

//例1 function Fun() { this.name = 'haha'; return {}; } var stu = new Fun(); console.log(stu.name); //undefined,stu為{} //例2 function Fun() { this.name = 'haha'; return function(){}; } var stu = new Fun(); console.log(stu.name); //undefined //例3 function Fun() { this.name = 'haha'; return 123; } var stu = new Fun(); console.log(stu.name); //haha,stu為Fun的實(shí)例 //例4 function Fun() { this.name = 'haha'; return undefined; } var stu = new Fun(); console.log(stu.name); //haha

  可以看出:如果return的是一個(gè)對(duì)象,那么this會(huì)指向返回的對(duì)象,如果return的不是一個(gè)對(duì)象,那么this還是指向函數(shù)的實(shí)例。

  但是return的是null時(shí)比較特殊。雖然null也是對(duì)象,但是this還是指向函數(shù)的實(shí)例。

//例5 function Fun() { this.name = 'haha'; return null; } var stu = new Fun(); console.log(stu.name); //haha

二、call、bind、apply對(duì)this指向的影響

  call和apply只有參數(shù)不同,這里就只討論call,因?yàn)閏all和bind參數(shù)使用方法是一樣的。

  1、call是動(dòng)態(tài)的改變this的指向,即換個(gè)對(duì)象執(zhí)行原對(duì)象方法的方法,并立即執(zhí)行;

  2、bind是靜態(tài)改變this的指向,并返回一個(gè)修改后的函數(shù)。

  就拿開(kāi)始的題目最后一個(gè)輸出來(lái)說(shuō):

  如果只是使用call的話:在執(zhí)行到這兩句時(shí)動(dòng)態(tài)改變了this的指向,所以call(b)的輸出hello,call(a)的輸出haha。

getA.call(b);//hello getA.call(a);//haha

  接下來(lái)看有bind影響的:

var getA2 = getA.bind(a);

  這里getA其實(shí)是a.getA,那么getA.bind(a)將this指向a,其實(shí)還是返回了a.getA函數(shù)賦值給了getA2。注意:其實(shí)函數(shù)沒(méi)有變化,但是內(nèi)部已經(jīng)將this指向了a

getA2.call(b);//haha //相當(dāng)于a.getA.call(b);

  此時(shí)無(wú)論call里是a還是b,都會(huì)輸出haha,因?yàn)閮?nèi)部的this已經(jīng)被bind綁定指向bind里面的a了。怎么理解呢,看下面示例:

var getA2 = getA.bind(a); var getA3 = getA.bind(b); getA2.call(b);//haha getA3.call(b);//hellovar getA2 = getA.bind(a); var getA3 = getA2.bind(b); getA2.call(b);//haha getA3.call(b);//haha

  使用bind靜態(tài)指定this:第一次使用bind后,this就被固定為bind的參數(shù)了,call、apply、bind均無(wú)法改變。

  如果new一下,this就是指向當(dāng)前構(gòu)造函數(shù)的實(shí)例;其他情況,this一直被靜態(tài)綁定為a

var a = {a:"haha",getA:function(){this.c = "12345678";console.log(this,this.a);} } var b = {a:"hello"} var getA = a.getA; var getA2 = getA.bind(a); var getA3 = getA2.bind(b); var getObj = new getA3();//new一下,this就是當(dāng)前構(gòu)造函數(shù)的實(shí)例 getA3();//其他情況,this一直被靜態(tài)綁定為a

  總的來(lái)說(shuō),call方法是在調(diào)用時(shí)改變this并立即執(zhí)行這個(gè)函數(shù),bind方法可以先改變函數(shù)中的this,之后對(duì)應(yīng)的函數(shù)可以在需要的時(shí)候再調(diào)用。

三、call、bind、apply用法:

  1、fun.apply(context,[argsArray])

  立即調(diào)用fun,同時(shí)將fun函數(shù)原來(lái)的this指向傳入的新context對(duì)象,實(shí)現(xiàn)同一個(gè)方法在不同對(duì)象上重復(fù)使用

  context:傳入的對(duì)象,替代fun函數(shù)原來(lái)的this;

  argsArray:一個(gè)數(shù)組或者類(lèi)數(shù)組對(duì)象,其中的數(shù)組參數(shù)會(huì)被展開(kāi)作為單獨(dú)的實(shí)參傳給 fun 函數(shù),需要注意參數(shù)的順序。?

  2、fun.call(context,[arg1],[arg2],[…])

  同apply,只是參數(shù)列表不同,call的參數(shù)需要分開(kāi)一個(gè)一個(gè)傳入。如果不知道參數(shù)個(gè)數(shù),則使用apply。

  使用:

Math.max() //只接收單獨(dú)的參數(shù),通過(guò)下面的方法可以在數(shù)組上面使用max方法: Math.max.apply(null, array); //會(huì)將array數(shù)組參數(shù)展開(kāi)成單獨(dú)的參數(shù)再傳入 Array.prototype.push.apply(arr1,arr2); //將一個(gè)數(shù)組拆開(kāi)push到另一個(gè)數(shù)組中;不用apply則會(huì)將后續(xù)數(shù)組參數(shù)當(dāng)成一個(gè)元素push進(jìn)去。 Array.prototype.slice.call(arguments); //在類(lèi)素組對(duì)象上使用slice方法 function isArray(obj){return Object.prototype.toString.call(obj) === '[object Array]' ; } //驗(yàn)證是否是數(shù)組

  3、fun.bind(context,[arg1],[arg2],[…])

  使fun方法執(zhí)行的context永不變。靜態(tài)指定this

  arg1:要傳遞到新函數(shù)的參數(shù)列表

  返回一個(gè)函數(shù)供后續(xù)調(diào)用,其函數(shù)體和原函數(shù)fun一樣,但新函數(shù)的this指向新傳入的context對(duì)象。新函數(shù)會(huì)具有bind方法指定的初始參數(shù)arg1/arg2...,后續(xù)調(diào)用新函數(shù)時(shí)的實(shí)參要往已有參數(shù)的后面排。就是科里化方式,綁定默認(rèn)的參數(shù),后面的參數(shù)可以變化。

  使用:

//原來(lái)的函數(shù)有4個(gè)參數(shù) var displayArgs = function (val1, val2, val3, val4) {console.log(val1 + " " + val2 + " " + val3 + " " + val4); } var emptyObject = {}; // 生成新函數(shù)時(shí)bind方法指定了2個(gè)參數(shù),則新函數(shù)會(huì)帶著這個(gè)兩個(gè)實(shí)參 var displayArgs2 = displayArgs.bind(emptyObject, 12, "a"); // 調(diào)用時(shí)傳入另2個(gè)參數(shù),要在bind方法傳入的2個(gè)實(shí)參后面 displayArgs2("b", "c"); // Output: 12 a b c

  bind的參數(shù)可以在執(zhí)行的時(shí)候再次添加,但是要注意的是,參數(shù)需要按照形參的順序添加

var demoObj = {name:"haha",fun:function(a,b,c){console.log(a,b,c);} } var newFun = demoObj.fun; var newFun2 = newFun.bind(demoObj,5); newFun2(7,9);//5,7,9

?

轉(zhuǎn)載于:https://www.cnblogs.com/goloving/p/7259988.html

總結(jié)

以上是生活随笔為你收集整理的深入理解this和call、bind、apply对this的影响及用法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。