這部分比較簡單,直接看代碼吧:javascript
function hello() { console.log('Hello, World'); } // 函數的調用 hello(); // Hello, World var obj = { welcome: function() { console.log('Hello, ' + this.name); }, name: 'dreamapple' }; // 方法調用 obj.welcome(); // Hello, dreamapple function Student(name, age) { this.name = name; this.age = age; console.log('My name is ' + this.name + ', and my age is ' + this.age); } // 構造函數的調用 var s = new Student('dreamapple', 23); // My name is dreamapple, and my age is 23
注意 :java
函數調用將全局對象(處於嚴格模式下則爲undefined)做爲接收者。通常不多使用函數調用語法來調用方法。數組
方法調用將被查找方法屬性的對象做爲調用接受者。閉包
構造函數須要經過new運算符調用,併產生一個新的對象做爲其接受者。app
JavaScript中將函數做爲參數或返回值的函數被稱爲高階函數,下面介紹一些經常使用的JS內置高階函數函數
sort
函數須要使用者傳入一個排序規則,以下:this
var arr = [1, 9, 3, 4, 2]; // 返回一個排序的結果 var arr1 = arr.sort(function(x, y) {return x>y?1:-1}); console.log(arr1); // [ 1, 2, 3, 4, 9 ]
使用 map
能夠簡化對數組的遍歷操做,其參數爲一個函數,以下:code
var arr = [1, 9, 3, 4, 2]; var arr2 = arr.map(function(x) { return x * 2 + 1; }); console.log(arr2); // [ 3, 5, 7, 9, 19 ] var arr3 = [1.4,1.5,3.2,3.6] arr3 = arr3.map(Math.ceil) console.log(arr3)//[2, 2, 4, 4]
使用call方法自定義接受者來調用函數。對象
使用call方法能夠調用在給定的對象中不存在的方法。排序
使用call方法定義高階函數容許使用者給回掉函數指定接收者。
// 使用call var obj1 = { sayHello: function(msg) { console.log('Hello,' + this.name + ' ' + msg); }, name: 'dreamapple' }; var obj2 = { name: 'dream' }; // 第一個參數是方法的調用者,剩餘的參數就是原函數的參數 obj1.sayHello.call(obj2, 'haha'); // Hello,dream haha // 高階函數使用call function compute(arg) { var sum = 0; for(var i = 0; i < arg.length; i++) { sum += arg[i]; } return sum; } function highFunc() { return compute.call(null, arguments); } console.log(highFunc(1, 2, 3, 4, 5)); // 15 var arr = [1,2,3,4,5]; console.log(highFunc(arr)); // 錯誤
JavaScript給每一個函數都隱式地提供了一個局部變量 arguments
使用隱式的arguments對象實現可變參數的函數。
考慮對可變參數的函數提供一個額外的固定元數的版本,從而使使用者無需藉助apply方法。
// 多參數函數 function multArgsFunc() { console.log(arguments); //[1, 2, 3, 4, 5] var sum = 0; for(var i = 0; i < arguments.length; i++) { sum += arguments[i]; } return sum; } console.log(multArgsFunc(1, 2, 3, 4)); // 10 console.log(multArgsFunc(1, 2, 3, 4, 5)); // 15
注意:
永遠不要直接修改arguments對象
arguments
是一個對象,不是數組,能夠經過 [].slice.call(arguments)
將其複製到一個真正的數組中再進行操做
當使用 arguments
時小心函數嵌套,一般應該使用變量保存 arguments
的引用
使用apply方法指定一個可計算的的參數數組來調用可變參數的函數。
使用apply方法的第一個參數給可變參數的的方法提供一個接收者。
注意:
apply的用法和call相似,惟一的區別在於call不接受參數數組,而apply能夠接受參數數組,即便參數個數固定只有一個或兩個,使用apply時也須要將參數用 []
包裹起來,例子以下:
// 使用apply function compute() { var sum = 0; for(var i = 0; i < arguments.length; i++) { sum += arguments[i]; } return sum; } function wrapper(arr) { return compute.apply(null, arr); // 給compute函數傳遞多個參數 } var arr = [1, 2, 3, 4, 5]; console.log(wrapper(arr)); // 15
使用 bind
來提取具備肯定接受者的方法
要注意, 提取一個方法不會將方法的接受者綁定到該方法的對象上。
當給高階函數傳遞對象方法時,使用匿名函數在適當的接受者上調用該方法。
使用bind方法建立綁定到適當接收者的函數。
調用 f.bind(someObject)
會產生一個新的函數對象。在這個新的函數對象中,this被永久綁定到了bind的第一個參數上面,不管後期這個新的函數被如何使用。
示例以下:
function f(){ return this.a; } var g = f.bind({a:"jack"}); console.log(g()); // jack var o = {a:37, f:f, g:g}; console.log(o.f(), o.g()); // 37, jack function Person(name){ this.nickname = name; this.distractedGreeting = function() { setTimeout(function(){ console.log("Hello, my name is " + this.nickname); }, 500); } } var alice = new Person('Alice'); alice.distractedGreeting(); //Hello, my name is undefined function Person(name){ this.nickname = name; this.distractedGreeting = function() { setTimeout(function(){ console.log("Hello, my name is " + this.nickname); }.bind(this), 500); // <-- this line! } } var alice = new Person('Alice'); alice.distractedGreeting(); // after 500ms logs "Hello, my name is Alice" this.x = 9; var module = { x: 81, getX: function() { return this.x; } }; module.getX(); // 81 var getX = module.getX; getX(); // 9, 由於在這個例子中,"this"指向全局對象 // 建立一個'this'綁定到module的函數 var boundGetX = getX.bind(module); boundGetX(); // 81
當調用函數的toString方法時,並無要求JavaScript引擎可以精確地獲取到函數的源代碼。
因爲在不一樣的引擎下調用toString方法的結果可能不一樣,因此絕對不要信賴函數源代碼的詳細細節。
toString方法的執行結果並不會暴露存儲在閉包中的局部變量值。
一般狀況下,應該避免使用函數對象的toString方法。
(function(x) { return x + 1; }).toString(); /* * 輸出結果 * function (x) { * return x + 1; * } * */ (function(x) { return x + 1; }).bind(10).toString(); /* * 因爲使用了宿主環境的內置庫提供的函數,JavaScript引擎會視圖提供該函數的源代碼的真實表示 * 而宿主環境中bind一般是其餘語言(如C++)提供的是一個編譯後的函數 * function (x) { [native code] } * */ (function(x) { return function(y) { return x + y; } }).bind(20).toString(); /* * function () { [native code] } * */