Function對象(apply、call、bind)javascript
原創文章,轉摘請註明出處:蘇福:http://www.cnblogs.com/susufufu/p/5850180.htmlhtml
本文參考MDN作的詳細整理,方便你們參考[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript)java
Function 構造器會建立一個新的 Function 對象。 在 JavaScript 中每一個函數都是一個Function對象。web
構造器數組
new Function ([arg1[, arg2[, ...argN]],] functionBody)瀏覽器
例:var adder = new Function("a", "b", "return a + b"); // 建立了一個能返回兩個參數和的函數閉包
adder(2, 6); // 8app
使用Function構造器生成的Function對象是在函數建立時解析的。這比你使用函數聲明或者函數表達式(function)並在你的代碼中調用更爲低效,由於使用後者建立的函數是跟其餘代碼一塊兒解析的。dom
全部被傳遞到構造函數中的參數,都將被視爲將被建立的函數的參數,而且是相同的標示符名稱和傳遞順序。函數
使用Function構造器生成的函數,並不會在建立它們的上下文中建立閉包;它們通常在全局做用域中被建立。當運行這些函數的時候,它們只能訪問本身的本地變量和全局變量,不能訪問Function構造器被調用生成的上下文的做用域。這和使用帶有函數表達式代碼的 eval 不一樣。
屬性:
length 是函數對象的一個屬性值,指明該函數指望多少個參數,即形參的個數。數量不包括剩餘參數。相比之下, arguments.length 是函數被調用時實際傳參的個數。
方法
Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])
在一個對象thisArg的上下文中應用另外一個對象的方法;參數可以以列表形式傳入,即在使用一個指定的this值(thisArg)和若干個指定的參數值的前提下調用某個函數或方法。
function greet() { var reply = [this.person, 'Is An Awesome', this.role].join(' '); console.log(reply); } var a = { person: 'Douglas Crockford', role: 'Javascript Developer' }; greet.call(a); // Douglas Crockford Is An Awesome Javascript Developer
function Food(name, price) { Product.call(this, name, price); this.category = 'food'; }
for(var i =0;i<10;i++){ setTimeout(function(){ console.log(i); }.call(null,i),0) } //能夠順利輸出0~9,若是不用call,則i的最終值,輸出10個10
Function.prototype.apply(thisArg[, argsArray])
在一個對象的上下文中應用另外一個對象的方法;參數可以以數組形式傳入。
使用apply和內置函數
聰明的apply用法容許你在某些原本須要寫成遍歷數組變量的任務中使用內建的函數。在接下里的例子中咱們會使用Math.max/Math.min來找出一個數組中的最大/最小值。
var numbers = [5, 6, 2, 3, 7]; var max = Math.max.apply(null, numbers); var min = Math.min.apply(null, numbers);
function minOfArray(arr) { var min = Infinity; var QUANTUM = 32768; for (var i = 0, len = arr.length; i < len; i += QUANTUM) { var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len))); min = Math.min(submin, min); } return min; } var min = minOfArray([5, 6, 2, 3, 7]);
Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])
bind()方法會建立一個新函數(新函數與被調函數具備相同的函數體)稱爲綁定函數。
function Point(x, y) { this.x = x; this.y = y; } Point.prototype.add = function() { return this.x + this.y; }; var p = new Point(1, 2); console.log(p); //Point { x: 1, y: 2 } var YAxisPoint = Point.bind({}, 5); var x = new YAxisPoint(6); console.log(x); //Point { x: 5, y: 6 } console.log(x.add()); //11
bind() 最簡單的用法是爲原函數建立一個綁定函數,綁定到指定的對象上,使這個函數不論怎麼調用都有一樣的 this 值
this.x = 9; var module = { x: 81, getX: function() { return this.x; } }; module.getX(); // 返回 81 var retrieveX = module.getX; retrieveX(); // 返回 9, 在這種狀況下,"this"指向所有做用域 // 建立一個新函數,將"this"綁定到module對象 // 新手可能會被全局的x變量和module裏的屬性x所迷惑 var boundGetX = retrieveX.bind(module); boundGetX(); // 返回 81
bind()的另外一個最簡單的用法是使一個函數擁有預設的初始參數
function list() { return Array.prototype.slice.call(arguments); } var list1 = list(1, 2, 3); // [1, 2, 3] var leadingThirtysevenList = list.bind(undefined, 37); var list2 = leadingThirtysevenList(); // [37] var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]
function foo(x,y){ return y ? x+y : foo.bind(void 0,x) } console.log(foo(1,4)); //3 console.log(foo(1)(4)); //3
配合 setTimeout,在默認狀況下,使用 window.setTimeout() 時,this 關鍵字會指向 window (或全局)對象。當使用類的方法時,須要 this 引用類的實例,你可能須要顯式地把 this 綁定到回調函數以便繼續使用實例。
function LateBloomer() { this.petalCount = Math.ceil(Math.random() * 12) + 1; } LateBloomer.prototype.bloom = function() { window.setTimeout(this.declare.bind(this), 1000); }; LateBloomer.prototype.declare = function() { console.log('I am a beautiful flower with ' + this.petalCount + ' petals!'); }; var flower = new LateBloomer(); flower.bloom(); // 一秒鐘後, 調用\'declare\'方法
獲取函數的實現源碼的字符串。覆蓋了 Object.prototype.toString 方法。