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