摘要:函數(shù)的調(diào)用者是異步函數(shù),不會(huì)為回調(diào)函數(shù)指定值。值為表示在全局對(duì)象下執(zhí)行該函數(shù)執(zhí)行方法,返回一個(gè)函數(shù)作為回調(diào)函數(shù),并且將需要向它傳遞的作為參數(shù)。
重要
函數(shù)中的thisJavaScript的this是有函數(shù)求值是的調(diào)用者決定的
JavaScript的this是有函數(shù)求值是的調(diào)用者決定的
JavaScript的this是有函數(shù)求值是的調(diào)用者決定的
函數(shù)中的this在調(diào)用時(shí)才有意義,函數(shù)的調(diào)用者決定函數(shù)中this的指向,每個(gè)函數(shù)調(diào)用時(shí)都會(huì)有this屬性。
function Point2D(x, y) { this.x = x; this.y = y; } Point2D.prototype.showLength = function() { var length = Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2)); console.log(length); }; Point2D.prototype.showLengthAsync = function() { var self = this; // 將this的值保存下來(lái),傳入異步函數(shù) setTimeout(function() { // setTimeout是異步函數(shù),在調(diào)用回調(diào)函數(shù)時(shí)沒(méi)有指定匿名函數(shù)的this, self.showLength(); //因?yàn)榛卣{(diào)函數(shù)沒(méi)有指定this,非嚴(yán)格模式下默認(rèn)指向全局對(duì)象 }, 1000); }; var x = 30, y = 40; var p = new Point2D(3, 4); var f = Point2D.prototype.showLength;
1.f():輸出50,因?yàn)楹瘮?shù)Point2D.prototype.showLength的調(diào)用者是變量f,變量f、x、y、Ponit2D函數(shù)在同一個(gè)對(duì)象中。
所以函數(shù)Point2D.prototype.showLength中this指向的是包含變量f、x、y、Ponit2D函數(shù)的對(duì)象。
this.x = 30,this.y = 40,所以f()是輸出50;
Point2D.prototype.showLength = function() { var length = Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2)); console.log(length); };
2.setTimeout(p.showLength, 500); :延時(shí)500ms后輸出50。函數(shù)p.showLength的調(diào)用者是異步函數(shù)setTimeout,setTimeout不會(huì)為回調(diào)函數(shù)指定this值。
在非嚴(yán)格模式下,p.showLength中的this默認(rèn)指向全局變量
this.x = 30,this.y = 40,所以setTimeout(p.showLength, 500)延時(shí)500ms后輸出50;
借用bind()方法可以將函數(shù)綁定到對(duì)象上,即將函數(shù)內(nèi)的this指向bind(p)方法中傳入的p對(duì)象
setTimeout(p.showLength.bind(p), 500); // 延時(shí)500ms后輸出5,因?yàn)楹瘮?shù)p.showLength指向?qū)ο髉,p的x屬性為3,y屬性為4
3.p.showLengthAsync();: 延時(shí)1000ms后輸出5。
Point2D.prototype.showLengthAsync = function() { var self = this; // 將this的值保存下來(lái),傳入異步函數(shù) setTimeout(function() { // setTimeout是異步函數(shù),在調(diào)用回調(diào)函數(shù)時(shí)沒(méi)有指定匿名函數(shù)的this, self.showLength(); //因?yàn)榛卣{(diào)函數(shù)沒(méi)有指定this,非嚴(yán)格模式下默認(rèn)指向全局對(duì)象 }, 1000); };
p.showLengthAsync函數(shù)的調(diào)用者是p對(duì)象本身,由于setTimeout不會(huì)為回調(diào)函數(shù)指定this值。所以在p.showLengthAsync函數(shù)中使用變量self將p.showLengthAsync函數(shù)調(diào)用的this值(即對(duì)象p)保存下來(lái)
回調(diào)函數(shù)中才可以利用變量self訪問(wèn)到對(duì)象p,完成正確調(diào)用;
4.箭頭函數(shù)
箭頭函數(shù)很特殊,箭頭函數(shù)中沒(méi)有定義this,所以可以使用外層函數(shù)的this。
Point2D.prototype.showLengthAsync = function() { setTimeout( () => this.showLength(), 1000); // 箭頭函數(shù)沒(méi)有定義this,可以訪問(wèn)外層函數(shù)的this };call()
函數(shù)的call()方法可以指定函數(shù)調(diào)用時(shí)的this值。函數(shù)中調(diào)用時(shí)的this值是可以改變的
并且,call()方法可以從第二個(gè)參數(shù)開始,指定傳入調(diào)用函數(shù)的參數(shù),以逗號(hào)分隔(多個(gè)原始形式的參數(shù))
function Point2D(x, y) { this.x = x; this.y = y; } Point2D.prototype.showLength = function() { var length = Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2)); console.log(length); }; var p = new Point2D(1, 1); console.log(p.showLength()); // ==> 1.4142... 調(diào)用p.length方法的是p對(duì)象本身,所以this.x和this.y均等于1 var obj = {x: 3, y: 4}; console.log(p.showLength.call(obj)); // ==> 5 使用函數(shù)p.showLength的call()方法改變函數(shù)調(diào)用時(shí)this的指向, //使其指向?qū)ο髈bj,所以this.x=3,this.y=4 function foo() { // 使用Array.prototype.slice函數(shù)的call()方法指定函數(shù)調(diào)用時(shí)的this指向arguments對(duì)象,將其切分為數(shù)組 var args = Array.prototype.slice.call(arguments); console.log(Array.isArray(arguments)); // false console.log(Array.isArray(args)); // true }
apply()call()的作用:改變當(dāng)前函數(shù)調(diào)用時(shí)的this值
函數(shù)的apply()方法與call()方法作用完全一致,只是在調(diào)用時(shí)傳入的參數(shù)有區(qū)別:
call()方法:第一個(gè)參數(shù)接收新的this值,后面的參數(shù)逗號(hào)分隔,逐個(gè)排列,傳入調(diào)用函數(shù)中
apply()方法:第一個(gè)參數(shù)接收新的this值,第二個(gè)參數(shù)接收一個(gè)數(shù)組,將數(shù)組整體作為參數(shù)傳入調(diào)用函數(shù)中
// 定義一個(gè)函數(shù),實(shí)現(xiàn)一種變換,將傳入其中的函數(shù)中參數(shù)的順序顛倒 function __reverseArgs__(fn) { return function() { var args = Array.prototype.slice.call(arguments); return fn.apply(this, args.reverse()); // 這里的this表示這個(gè)匿名函數(shù)的調(diào)用者 }; } var foo = function() {console.log(Array.from(arguments));}; var foo2 = __reverseArgs__(foo); foo2(1, 2, 3, 4);
注意return fn.apply(this, args.reverse());中的this。因?yàn)?b>__reverseArgs__(fn)函數(shù)返回一個(gè)新的函數(shù),apply()中的this指向調(diào)用這個(gè)新函數(shù)的對(duì)象。
foo2接收了__reverseArgs__(foo)返回的新函數(shù),調(diào)用foo2(1, 2, 3, 4)時(shí),因?yàn)?b>foo2在全局對(duì)象下,所以this的值是全局對(duì)象。
__reverseArgs__(fn)方法應(yīng)該只改變傳入函數(shù)中參數(shù)的順序,不改變?cè)瓉?lái)函數(shù)調(diào)用的作用域。所以使用this將函數(shù)的調(diào)用改回傳入函數(shù)的作用域。
bind()bind()方法與call()和apply()方法的最大區(qū)別在于返回值:call()和apply()都會(huì)立即執(zhí)行,返回結(jié)果;而bind()方法會(huì)返回一個(gè)函數(shù),并且可以通過(guò)bind()向函數(shù)中傳遞已經(jīng)確定的參數(shù),對(duì)于異步調(diào)用很有幫助。
function add(x, y) { return x + y; } // call()和apply()會(huì)立即執(zhí)行;bind()方法會(huì)返回一個(gè)函數(shù)對(duì)象 console.log(add.call(null, 1, 2)); // ==> 3 ,使用call()方法在全局對(duì)象下對(duì)傳入的參數(shù)1,2執(zhí)行函數(shù) console.log(add.apply(null, [1, 2])); // ==> 3 apply()方法在全局對(duì)象下對(duì)傳入的參數(shù)1,2執(zhí)行函數(shù) console.log(add.bind(null, 1, 2)); // ==> function () { [native code] }, 返回一個(gè)函數(shù) // 傳入兩個(gè)參數(shù) let add1 = add.bind(null, 1, 2); // bind()方法執(zhí)行時(shí),將1和2對(duì)應(yīng)傳遞給x,y,返回一個(gè)函數(shù)。再調(diào)用返回的函數(shù)時(shí),不用再傳遞參數(shù) console.log(add1()); // ==> 3 為傳遞參數(shù),直接調(diào)用,使用bind()時(shí)傳入的參數(shù)值 // 傳入一個(gè)參數(shù) let add2 = add.bind(null, 1); //bind()時(shí)只傳遞一個(gè)參數(shù)1給x,返回一個(gè)函數(shù),在調(diào)用返回函數(shù)時(shí)只需炫迪一個(gè)參數(shù)給y即可 console.log(add2(3)); // ==> 4 只需傳遞一個(gè)參數(shù)給y即可 // 不傳遞參數(shù) let add3 = add.bind(null); //調(diào)用bind()時(shí)不傳遞參數(shù),返回一個(gè)函數(shù),在調(diào)用返回函數(shù)時(shí)要傳遞2個(gè)參數(shù) console.log(add3(2, 3)); // ==> 5 需要傳遞兩個(gè)參數(shù),與調(diào)用原函數(shù)沒(méi)有區(qū)別。。。不建議使用
可以看出bind()的最大用處在于返回一個(gè)函數(shù),并且可以向函數(shù)內(nèi)傳遞確定的參數(shù)值(在bind()執(zhí)行時(shí)時(shí)便已經(jīng)確定的參數(shù))。調(diào)用返回的函數(shù)時(shí),無(wú)需再傳入bind()時(shí)傳入的參數(shù)---實(shí)現(xiàn)函數(shù)的部分調(diào)用
應(yīng)用場(chǎng)景:類似于setTimeout(fn, 1000);的異步函數(shù),需要一個(gè)函數(shù)作為參數(shù),在1s后執(zhí)行。有時(shí)對(duì)于已經(jīng)知道fn調(diào)用時(shí)傳入的參數(shù)值時(shí),便可以使用bind(),先將參數(shù)傳遞進(jìn)去,返回一個(gè)函數(shù);等待時(shí)間到后,無(wú)需再向該函數(shù)傳入?yún)?shù),立即執(zhí)行即可
function setBodyState(state) { document.body.className = state; } setBodyState.call(null, "state1"); // 立即執(zhí)行setBodyState函數(shù),將document.body.className設(shè)置為"state1"。 // this值為null表示在全局對(duì)象下執(zhí)行該函數(shù) setTimeout(setBodyState.bind(null, "state2"), 1500); // 執(zhí)行bind()方法,返回一個(gè)函數(shù)作為回調(diào)函數(shù),并且將需要向它傳遞 //的"state2"作為參數(shù)。1500ms后立即執(zhí)行返回的函數(shù)即可,無(wú)需再傳入?yún)?shù)
bind()方法在異步函數(shù)中的應(yīng)用,主要由于其返回一個(gè)函數(shù),并且可以傳入?yún)?shù)值的特性,可以減少異步函數(shù)調(diào)用的部分問(wèn)題。
高階函數(shù)實(shí)例 Closure中訪問(wèn)外部函數(shù)的arguments、this、形參和局部變量// __multi__()抽象一個(gè)過(guò)程,將傳入的函數(shù)進(jìn)行擴(kuò)展,使其第一個(gè)參數(shù)接收類數(shù)組 // 調(diào)用原來(lái)的方法fn對(duì)每個(gè)第一個(gè)數(shù)組參數(shù)中的每個(gè)元素執(zhí)行fn方法 function __multi__(fn) { return function(arrayLike, ...args) { return Array.from(arrayLike).map(item => fn(item, ...args)); }; } function __multi__(fn) { return function(arrayLike, ...args) { // 返回一個(gè)函數(shù)(創(chuàng)建一個(gè)Closure),返回的函數(shù)接收夜歌類數(shù)組對(duì)象和rest參數(shù)作為參數(shù) return Array.from(arrayLike).map(function(value) { return fn(value, ...args); }); }; } function add(x, y) { return x + y;} var add2 = __multi__(add); console.log(add2([1,2,3], 4)); // ==> [5, 6, 7]
1.注意map()方法如果需要返回值,一定要在傳入map()的函數(shù)中返回值,因?yàn)槟J(rèn)的返回值是undefined`
2.Closure中對(duì)于外層函數(shù)的局部變量、形參、實(shí)參對(duì)象arguments和this的訪問(wèn)問(wèn)題:
__multi__()返回一個(gè)函數(shù)(創(chuàng)建一個(gè)Closure),返回的函數(shù)保留對(duì)外層函數(shù)作用域的訪問(wèn)能力
但this值和實(shí)參對(duì)象arguments是根據(jù)調(diào)用函數(shù)時(shí)確定的,如果要在Closure中訪問(wèn)到調(diào)用時(shí)的this和arguments對(duì)象,需要將其保存在外部函數(shù)局部作用域的變量中。
function __multi__(fn) { var self = this; var outerArgs = arguments; return function(arrayLike, ...args) { return Array.from(arrayLike).map(function(value) { console.log(self); // 可以訪問(wèn)到外層函數(shù)的調(diào)用者 console.log(outerArgs); //可以訪問(wèn)到外層函數(shù)的實(shí)參列表,相當(dāng)于訪問(wèn)外層函數(shù)的局部變量 console.log(this); // 訪問(wèn)到的this值是返回函數(shù)的調(diào)用者 console.log(arguments); // 訪問(wèn)到的arguments是傳入返回函數(shù)的實(shí)參 return fn(value, ...args); // 可以訪問(wèn)到外部函數(shù)的形參 }); }; }
Closure中可以訪問(wèn)到外部函數(shù)的形參(形參的特性與局部變量相同)
function __multi__(fn, a = 2) { console.log(arguments[0]); return function(arrayLike, ...args) { return Array.from(arrayLike).map(function(value) { console.log(a); // 可以訪問(wèn)到外層函數(shù)的形參a return fn(value, ...args); // 可以訪問(wèn)到外部函數(shù)的形參fn }); }; }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/82074.html
摘要:所以相同點(diǎn)是,在全局范圍內(nèi),全局變量終究是屬于老大的。只生效一次引入了。只生效一次在箭頭函數(shù)中,與封閉詞法環(huán)境的保持一致。我通常把這些原始函數(shù)叫做構(gòu)造函數(shù)。在里面你可以嵌套函數(shù),也就是你可以在函數(shù)里面定義函數(shù)。 showImg(https://img-blog.csdnimg.cn/20190522000008399.jpg?x-oss-process=image/watermark,...
摘要:關(guān)鍵字計(jì)算為當(dāng)前執(zhí)行上下文的屬性的值。毫無(wú)疑問(wèn)它將指向了這個(gè)前置的對(duì)象。構(gòu)造函數(shù)也是同理。嚴(yán)格模式無(wú)論調(diào)用位置,只取顯式給定的上下文綁定的,通過(guò)方法傳入的第一參數(shù),否則是。其實(shí)并不屬于特殊規(guī)則,是由于各種事件監(jiān)聽定義方式本身造成的。 this 是 JavaScript 中非常重要且使用最廣的一個(gè)關(guān)鍵字,它的值指向了一個(gè)對(duì)象的引用。這個(gè)引用的結(jié)果非常容易引起開發(fā)者的誤判,所以必須對(duì)這個(gè)關(guān)...
摘要:箭頭函數(shù)沒(méi)有自己的值,箭頭函數(shù)中所使用的來(lái)自于函數(shù)作用域鏈。使用箭頭函數(shù)打印對(duì)于內(nèi)層函數(shù),它本身并沒(méi)有值,其使用的來(lái)自作用域鏈,來(lái)自更高層函數(shù)的作用域。 《JavaScript 深入淺出》系列: JavaScript 深入淺出第 1 課:箭頭函數(shù)中的 this 究竟是什么鬼? JavaScript 深入淺出第 2 課:函數(shù)是一等公民是什么意思呢? 普通函數(shù)與箭頭函數(shù) 普通函數(shù)指的是...
摘要:想想也是難以置信,這應(yīng)該全歸功于對(duì)框架的依賴,促使助長(zhǎng)了自己對(duì)學(xué)習(xí)的懈怠。真正的成了離職就失業(yè)的尷尬境地。我們接下來(lái)來(lái)了解下中的的使用和作用。以前對(duì)中的理解很簡(jiǎn)單粗暴誰(shuí)調(diào)用就指向誰(shuí)。如果例題中有不對(duì)的地方希望予以指教留言評(píng)論 前言 使用JavaScript有很長(zhǎng)一段時(shí)間了,但是以前過(guò)多都是使用,從不去及理解其中原理,單單只是去生拼硬湊。這樣的開發(fā)居然做了2年。匪夷所思居然項(xiàng)目中Java...
摘要:原文鏈接參考深入理解原型和閉包完結(jié)王福朋博客園中的作用域詳解博客園 前言 王福朋老師的 JavaScript原型和閉包系列 文章看了不下三遍了,最為一個(gè)初學(xué)者,每次看的時(shí)候都會(huì)有一種 大徹大悟 的感覺(jué),而看完之后卻總是一臉懵逼。原型與閉包 可以說(shuō)是 JavaScirpt 中理解起來(lái)最難的部分了,當(dāng)然,我也只是了解到了一些皮毛,對(duì)于 JavaScript OOP 更是缺乏經(jīng)驗(yàn)。這里我想總...
摘要:注意該方法的作用和方法類似,只有一個(gè)區(qū)別,就是方法接受的是若干個(gè)參數(shù)的列表,而方法接受的是一個(gè)包含多個(gè)參數(shù)的數(shù)組。指定的參數(shù)列表。返回值返回值是你調(diào)用的方法的返回值,若該方法沒(méi)有返回值,則返回。 溫馨提示:作者的爬坑記錄,對(duì)你等大神完全沒(méi)有價(jià)值,別在我這浪費(fèi)生命溫馨提示-續(xù):打call原本是屬于我們偶像宅文化中的專業(yè)名詞,指的是飯們?cè)诳磍ive時(shí)在臺(tái)下配合愛(ài)豆演出的節(jié)奏喊口號(hào),舉例:超...
閱讀 2696·2021-09-22 15:58
閱讀 2238·2019-08-29 16:06
閱讀 906·2019-08-29 14:14
閱讀 2815·2019-08-29 13:48
閱讀 2459·2019-08-28 18:01
閱讀 1504·2019-08-28 17:52
閱讀 3328·2019-08-26 14:05
閱讀 1622·2019-08-26 13:50