摘要:一函數(shù)調(diào)用的種模式方法調(diào)用模式當(dāng)一個(gè)函數(shù)被保存為對(duì)象的一個(gè)屬性時(shí),我們稱(chēng)它為一個(gè)方法。二函數(shù)常用的三個(gè)方法在指定值和參數(shù)參數(shù)以數(shù)組或類(lèi)數(shù)組對(duì)象的形式存在的情況下調(diào)用某個(gè)函數(shù)。當(dāng)綁定函數(shù)被調(diào)用時(shí),該參數(shù)會(huì)作為原函數(shù)運(yùn)行時(shí)的指向。
一、函數(shù)調(diào)用的4種模式 (1) 方法調(diào)用模式
當(dāng)一個(gè)函數(shù)被保存為對(duì)象的一個(gè)屬性時(shí),我們稱(chēng)它為一個(gè)方法。當(dāng)一個(gè)方法被調(diào)用時(shí),this 被綁定到該對(duì)象。如果調(diào)用表達(dá)式包含一個(gè)提取屬性的動(dòng)作(即包含一個(gè).點(diǎn)表達(dá)式或[subscript]下標(biāo)表達(dá)式),那么它就是被當(dāng)做一個(gè)方法來(lái)調(diào)用。
var myObj = { value: 0, increment: function (inc) { this.value += typeof inc === "number" ? inc : 1; } }; myObj.increment(); console.log(myObj.value); // 1 myObj.increment(2); console.log(myObj.value); // 3(2) 函數(shù)調(diào)用模式
var add = function (a,b) { return a + b; }; var sum = add(3,4); // sum的值為7
以此模式調(diào)用函數(shù)時(shí),this 被綁定到全局對(duì)象。
延伸:調(diào)用內(nèi)部函數(shù)時(shí),如何把 this 綁定到外部函數(shù)的 this 變量上
// 承接上面代碼 // 給 myObj 增加一個(gè) double 方法 myObj.double = function() { var that = this; // 解決方法 var helper = function () { console.log(this); // this指向全局對(duì)象,如果寫(xiě)成this.value = add(this.value, this.value); 就獲取不到正確的結(jié)果了 that.value = add(that.value, that.value); }; helper(); // 以函數(shù)的形式調(diào)用 helper }; myObj.double(); // 以方法的形式調(diào)用 double console.log(myObj.value); // 6(3) 構(gòu)造器調(diào)用模式
var Quo = function (string) { this.status = string; } var myQuo = new Quo("confused"); // 構(gòu)造一個(gè) Quo 實(shí)例 console.log(myQuo.status); // "confused"
一個(gè)函數(shù),如果創(chuàng)建的目的就是希望結(jié)合new前綴來(lái)調(diào)用,那它就被稱(chēng)為構(gòu)造(器)函數(shù),函數(shù)內(nèi)部的this 指向新創(chuàng)建的實(shí)例。
(4) apply、call調(diào)用模式js 是一門(mén)函數(shù)式的面向?qū)ο缶幊陶Z(yǔ)言,函數(shù)也是一個(gè)對(duì)象,所以函數(shù)可以擁有自己的方法,apply、call就是其中的兩種方法。
此種調(diào)用模式允許我們可以顯式地設(shè)置 this 的指向,具體使用見(jiàn)下文。
二、函數(shù)常用的三個(gè)方法 1. fun.apply(thisArg[, argsArray])在指定 this 值和參數(shù)(參數(shù)以數(shù)組或類(lèi)數(shù)組對(duì)象的形式存在)的情況下調(diào)用某個(gè)函數(shù)。
thisArg:在 fun 函數(shù)運(yùn)行時(shí)指定的 this 值,如果這個(gè)函數(shù)處于非嚴(yán)格模式下,則指定為 null 或 undefined 時(shí)會(huì)自動(dòng)指向全局對(duì)象(瀏覽器中就是window對(duì)象)
argsArray:一個(gè)數(shù)組或者類(lèi)數(shù)組對(duì)象,其中的數(shù)組元素將作為多帶帶的參數(shù)傳給 fun 函數(shù)。如果該參數(shù)的值為null 或 undefined,則表示不需要傳入任何參數(shù)。也可以使用 arguments 對(duì)象作為 argsArray 參數(shù),用arguments把所有的參數(shù)傳遞給被調(diào)用對(duì)象。
/* 求一個(gè)數(shù)組中的最大最小值 */ var numbers = [5, 6, 2, 3, 7]; /* simple loop based algorithm */ max = -Infinity, min = +Infinity; for (var i = 0; i < numbers.length; i++) { if (numbers[i] > max) max = numbers[i]; if (numbers[i] < min) min = numbers[i]; } /* vs. using Math.min/Math.max apply */ var max = Math.max.apply(null, numbers); /* This about equal to Math.max(numbers[0], ...) or Math.max(5, 6, ..) */ var min = Math.min.apply(null, numbers);
從上面的例子可以看到:本來(lái)需要寫(xiě)成遍歷數(shù)組變量的任務(wù),apply使用內(nèi)建的函數(shù)就完成了。據(jù)此,可以簡(jiǎn)化某些對(duì)數(shù)組的操作
var arr1 = [1,2,3]; var arr2 = [4,5,6]; /* 如果我們要把 arr2 展開(kāi),然后一個(gè)一個(gè)追加到 arr1 中去,最后讓 arr1=[1,2,3,4,5,6] * arr1.push(arr2)是不行的,因?yàn)檫@樣做會(huì)得到[1,2,3,[4,5,6]] * 可以循環(huán)arr2,然后一個(gè)一個(gè)的push,但是這樣比較麻煩,使用apply,就so easy了 */ Array.prototype.push.apply(arr1,arr2); console.log(arr1); // [1,2,3,4,5,6] /* 也可以用arr1.concat(arr2),但是concat方法返回的是一個(gè)新數(shù)組,并不改變arr1本身 */2. fun.call(thisArg[, arg1[, arg2[, ...]]])
該方法的作用和 apply() 方法類(lèi)似,只有一個(gè)區(qū)別,就是 call() 方法接受的是一個(gè)參數(shù)列表,而apply()方法接受的是一個(gè)包含多個(gè)參數(shù)的數(shù)組。
Math.max.apply(null, [1,2,3,4]); Math.max.call(null, 1, 2, 3, 4); /* eg. 使用call方法調(diào)用父構(gòu)造函數(shù) */ function Animal(name){ this.name = name; this.showName = function(){ console.log(this.name); } } function Cat(name){ Animal.call(this, name); // 此行代碼中的this指向Cat的實(shí)例 } var cat = new Cat("Black Cat"); cat.showName(); // "Black Cat"3. fun.bind(thisArg[, arg1[, arg2[, ...]]])
當(dāng)在函數(shù)fun上調(diào)用bind( )方法并傳入一個(gè)對(duì)象thisArg作為參數(shù),這個(gè)方法將返回一個(gè)新函數(shù)。調(diào)用新的函數(shù)將會(huì)把原始的函數(shù)fun當(dāng)做thisArg的方法來(lái)調(diào)用。
thisArg:當(dāng)綁定函數(shù)被調(diào)用時(shí),該參數(shù)會(huì)作為原函數(shù)運(yùn)行時(shí)的 this 指向。當(dāng)使用new 操作符調(diào)用綁定函數(shù)時(shí),該參數(shù)無(wú)效
arg1, arg2, ...:當(dāng)綁定函數(shù)被調(diào)用時(shí),這些參數(shù)加上綁定函數(shù)本身的參數(shù)會(huì)按照順序作為原函數(shù)運(yùn)行時(shí)的參數(shù)
// eg.1 var sum = function (x,y) { return x + y; }; var succ = sum.bind(null, 1); succ(2); // => 3: x綁定到1,并傳入2作為實(shí)參y // eg.2 function f(y,z) { return this.x + y + z; }; var g = f.bind({x:1}, 2); // 綁定this和y g(3); // =>6: this.x綁定到1,y綁定到2,z綁定到3 // eg.3 創(chuàng)建綁定函數(shù) this.x = 9; var module = { x: 81, getX: function() { return this.x; } }; module.getX(); // 81 var retrieveX = module.getX; retrieveX(); // 9, because in this case, "this" refers to the global object // Create a new function with "this" bound to module var boundGetX = retrieveX.bind(module); boundGetX(); // 81
bind 函數(shù)在ES5版本中才被加入,ES3版本的bind( )方法實(shí)現(xiàn)如下(js權(quán)威指南p191):
if (!Function.prototype.bind) { Function.prototype.bind = function(o[, args]) { var self = this, boundArgs = arguments; // bind()方法的返回值是一個(gè)函數(shù) return function() { // 創(chuàng)建一個(gè)實(shí)參列表,將傳入bind()的第二個(gè)及后續(xù)的實(shí)參都傳入這個(gè)函數(shù) var args = [], i; for(i = 1; i < boundArgs.length; i++) args.push(boundArgs[i]); for(i = 0; i < arguments.length; i++) args.push(arguments[i]); // 現(xiàn)在將self作為o的方法來(lái)調(diào)用,傳入這些實(shí)參 return self.apply(o, args); } } } /* 關(guān)鍵點(diǎn)有二:一是改變this的指向,二是改變傳入?yún)?shù)的個(gè)數(shù) * * 上述代碼并未實(shí)現(xiàn)ES5中bind方法的全部特性,但思路比較清晰明了,且滿(mǎn)足大部分需求了 */
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/79683.html
摘要:雖然這個(gè)模式運(yùn)行效果很不錯(cuò),但是如果嵌套了太多的回調(diào)函數(shù),就會(huì)陷入回調(diào)地獄。當(dāng)需要跟蹤多個(gè)回調(diào)函數(shù)的時(shí)候,回調(diào)函數(shù)的局限性就體現(xiàn)出來(lái)了,非常好的改進(jìn)了這些情況。 JavaScript引擎是基于單線程 (Single-threaded) 事件循環(huán)的概念構(gòu)建的,同一時(shí)刻只允許一個(gè)代碼塊在執(zhí)行,所以需要跟蹤即將運(yùn)行的代碼,那些代碼被放在一個(gè)任務(wù)隊(duì)列 (job queue) 中,每當(dāng)一段代碼準(zhǔn)...
摘要:作為對(duì)象原型鏈的終點(diǎn)。調(diào)用函數(shù)時(shí),應(yīng)該提供的參數(shù)沒(méi)有提供,該參數(shù)等于。它可以用于引用該函數(shù)的函數(shù)體內(nèi)當(dāng)前正在執(zhí)行的函數(shù)。 一 JS 二 CSS 一 JS ==和===的區(qū)別 ===叫做嚴(yán)格運(yùn)算符 ==叫做相等運(yùn)算符嚴(yán)格運(yùn)算符比較時(shí)不僅僅比較數(shù)值還要比較數(shù)據(jù)類(lèi)型是否一樣相等運(yùn)算符在比較相同類(lèi)型的數(shù)據(jù)時(shí),與嚴(yán)格相等運(yùn)算符完全一樣。 在比較不同類(lèi)型的數(shù)據(jù)時(shí),相等運(yùn)算符會(huì)先將數(shù)據(jù)進(jìn)行類(lèi)型轉(zhuǎn)換,...
摘要:作為對(duì)象原型鏈的終點(diǎn)。調(diào)用函數(shù)時(shí),應(yīng)該提供的參數(shù)沒(méi)有提供,該參數(shù)等于。它可以用于引用該函數(shù)的函數(shù)體內(nèi)當(dāng)前正在執(zhí)行的函數(shù)。 一 JS 二 CSS 一 JS ==和===的區(qū)別 ===叫做嚴(yán)格運(yùn)算符 ==叫做相等運(yùn)算符嚴(yán)格運(yùn)算符比較時(shí)不僅僅比較數(shù)值還要比較數(shù)據(jù)類(lèi)型是否一樣相等運(yùn)算符在比較相同類(lèi)型的數(shù)據(jù)時(shí),與嚴(yán)格相等運(yùn)算符完全一樣。 在比較不同類(lèi)型的數(shù)據(jù)時(shí),相等運(yùn)算符會(huì)先將數(shù)據(jù)進(jìn)行類(lèi)型轉(zhuǎn)換,...
摘要:前言初學(xué)總會(huì)對(duì)指向感到疑惑,想要深入學(xué)習(xí),必須先理清楚和相關(guān)的幾個(gè)概念。中總是指向一個(gè)對(duì)象,但具體指向誰(shuí)是在運(yùn)行時(shí)根據(jù)函數(shù)執(zhí)行環(huán)境動(dòng)態(tài)綁定的,而并非函數(shù)被聲明時(shí)的環(huán)境。除去不常用的和的情況,具體到實(shí)際應(yīng)用中,指向大致可以分為以下種。 前言 初學(xué)javascript總會(huì)對(duì)this指向感到疑惑,想要深入學(xué)習(xí)javascript,必須先理清楚和this相關(guān)的幾個(gè)概念。javascript中t...
摘要:寫(xiě)在前面金三銀四又到了一年一度的跳槽季相信大家都在準(zhǔn)備自己面試筆記我也針對(duì)自己工作中所掌握或了解的一些東西做了一個(gè)目錄總結(jié)方便自己復(fù)習(xí)詳細(xì)內(nèi)容會(huì)在之后一一對(duì)應(yīng)地補(bǔ)充上去有些在我的個(gè)人主頁(yè)筆記中也有相關(guān)記錄這里暫且放一個(gè)我的面試知識(shí)點(diǎn)目錄大家 寫(xiě)在前面: 金三銀四, 又到了一年一度的跳槽季, 相信大家都在準(zhǔn)備自己面試筆記, 我也針對(duì)自己工作中所掌握或了解的一些東西做了一個(gè)目錄總結(jié),方便自...
閱讀 1106·2021-10-12 10:11
閱讀 888·2019-08-30 15:53
閱讀 2304·2019-08-30 14:15
閱讀 2976·2019-08-30 14:09
閱讀 1212·2019-08-29 17:24
閱讀 987·2019-08-26 18:27
閱讀 1294·2019-08-26 11:57
閱讀 2171·2019-08-23 18:23