它究竟是什麼算法
String Array 都是系統內置對象(已經定義好,能夠直接使用)固然,這貨也是同樣,咱們以前定義的函數,其實就是一個這貨的實例。數組
在JS中,全部的對象都是由函數實現的,函數的數據類型是object。So,咱們之前定義的函數也是一個對象。閉包
幾種寫法app
1 function fn1(a,b){ 2 return a+b; 3 } 4 5 //前面表示參數,後面表示函數語句 6 var fn2 = new Function("a","b","return a+b"); 7 8 // 匿名函數 9 var fn3=function(a,b){ 10 return a+b; 11 } 12 13 14 console.log(fn1(1,2)); 15 console.log(fn2(1,2)); 16 console.log(fn3(1,2)); // 注意,必定要在聲明函數的後面調用
另外,若是函數沒有明確的返回值,或者調用了沒有參數的return,那麼它真正返回的值是undefineddom
1 function fn(){ 2 //..... 3 } 4 5 6 function fn1(){ 7 return; 8 } 9 10 11 console.log(fn()===undefined); // true 12 console.log(fn1()===undefined); // true
arguments 函數
arguments只有在代碼運行的時候才起做用,它是一個數組(準確的說是僞數組),保存函數的參數。this
1 function fn(){ 2 var sum=0; 3 for(var i=0;i<arguments.length;i++){ 4 sum+=arguments[i]; 5 } 6 return sum; 7 } 8 9 var sum = fn(1,2); 10 var sum2 = fn(1,2,3); 11 console.log(sum); // 3 12 console.log(sum2); // 6 13 14 function fn1(a,b,c,d){ 15 console.log(arguments.length); 16 console.log(arguments[0]); 17 } 18 19 fn1(); // 0 、 undefined 20 fn1(1); // 1 、 1 21 fn1('a',2); // 2 、 a 22 fn1('李志',2,3); // 3 、 李志 23 fn1('李B',2,2,3,4,4); // 6 、 李B
Lengthspa
咱們須要瞭解兩個東東,形參與實參(不一樣的資料書籍可能叫法有所差別)prototype
形參:函數定義的時候的參數 實參:調用函數的時候傳遞的參數code
length指的是形參個數 arguments.length指的是實參個數
1 function fn(a, b) { 2 console.log(fn.length); 3 console.log(arguments.length); 4 } 5 6 fn(1, 2); // 2 2 7 fn(1); // 2 1
call apply
1,借用另外一個對象的方法 2,替換this指向
Apply方法 調用函數,並用指定對象替換函數的this值,同時用指定數組替換函數的參數。
Call方法 調用一個對象的方法,用另外一個對象替換當前對象。
1 //對象1 2 var obj1={ 3 getAllStudentsNumbers:function(sum,sum1){ 4 return sum+sum1} 5 }; 6 7 //對象2 8 var obj2={ 9 getDetail:function(){ 10 return {name:'阿拉三',age:'18'} 11 } 12 }; 13 console.log(obj1.getAllStudentsNumbers.call(obj2,10,200)); // 210 14 console.log(obj1.getAllStudentsNumbers.apply(obj2,[10,200])); // 210
Function.apply(obj,args)方法能接收兩個參數
obj:這個對象將代替Function類裏this對象
args:這個是數組,它將做爲參數傳給Function(args-->arguments)
咱們經過以下方式將其轉換成數組
1 /* slice : 截取數組,返回的仍是數組,這裏咱們截取所有 */ 2 var divs = document.getElementsByTagName("div") 3 var domNodes = Array.prototype.slice.call(divs);
還能夠實現繼承,在上篇文章中說過,這裏不作贅述。
caller callee
caller屬性 獲取調用當前函數的函數。caller屬性只有當函數正在執行時才被定義。
返回函數調用者,主要用於察看函數自己被哪一個函數調用.
1 function fn() { 2 //判斷某函數是否被調用 3 if (fn.caller) { 4 alert(fn.caller.toString()); 5 } else { 6 alert("函數直接執行"); 7 } 8 } 9 10 function fn1() { 11 fn(); 12 } 13 fn1(); 14 fn();
callee屬性 返回正被執行的 Function 對象,即指定的Function 對象的正文。
以下是一個遞歸算法 - 計算 1+2+3+4+...+n
什麼是遞歸? 能夠這樣理解,一個方法,本身調用本身,用上一次調用得出的結果做爲此次的參數。
傳統方式的缺點:
一、破壞了,零重複法則,當一旦函數名稱更改,須要更改多處
二、fn是一個全局變量,fn內部通常使用局部變量,而這裏是一個全局變量,這是一個潛在的全局變量污染
1 var fn=function(n){ 2 return n>0 ? n+fn(n-1) : 0; 3 } 4 console.log('採用傳統方式:'+fn(10));
優勢:這樣就讓代碼更加簡練。又防止了全局變量的污染
1 var fn=(function(n){ 2 return n>0 ? n+arguments.callee(n-1) : 0; 3 })(10); 4 console.log('採用callee方式: '+fn);
constructor prototype
constructor屬性,就是用來構造對象實例的函數引用。
prototype屬性,獲取對象的原型。
每個構造函數都有一個prototype屬性,指向另外一個對象。這個對象的全部屬性和方法,都會被構造函數的實例繼承。這意味着,咱們能夠把那些不變的屬性和方法,直接定義在prototype對象上。
contructor,prototype屬性是系統自動生成的。但本質上只是是函數對象的屬性而已。
對象是一個函數,而函數對象含有contructor,prototype等屬性,
那麼實例化的過程就是拷貝構造函數屬性的過程,因此每一個實例天然就擁有了contructor,prototype這兩個屬性。
自定義對象:函數實現的--函數又是Function的一個實例,因此這個自定義對象含有Function對象的一切屬性和方法
1 var product = function(){} 2 /*自動有一個 prototype屬性 它是一個對象--- 原型對象*/ 3 /* product.prototype也是對象,對象都是函數實現的,這貨也包含Function對象的一切屬性和方法,因此他也有。*/ 4 product.prototype.buy=function(){} 5 product.prototype={}
bind
Bind方法,建立具備與原始函數相同的主體的綁定函數。 在綁定功能中,this對象解析爲傳入的對象。 該綁定函數具備指定的初始參數。
爲了能在改變了上下文以後繼續引用到this,你們一般選擇使用self that _this 等方式先保存起來。這是徹底能夠的,如今有了bind:
1 var obj={ 2 fn1:function(){ 3 console.log(1); 4 }, 5 fn2:function(){ 6 console.log(2); 7 }, 8 fn3:function(fn){ 9 fn(); 10 console.log(3); 11 }, 12 fn4:function(){ 13 // var that=this; // 還保存嗎? 14 // this.fn3(function(){ 15 // console.log(4); 16 // that.fn1(); 17 // that.fn2(); 18 // }); 19 this.fn3(function(){ 20 console.log(4); 21 this.fn1(); 22 this.fn2(); 23 }.bind(this)); // 咦,發生什麼? 24 }, 25 } 26 obj.fn4();
再看一眼:
1 var foo={ 2 x:3, 3 } 4 var bar=function(){ 5 console.log(this.x); 6 } 7 bar(); 8 var boundFunc=bar.bind(foo); 9 boundFunc();
想到了什麼?call? apply? 沒錯,看下面三者的區別:
1 fn1.hello.call(fn2,1,2,3); 2 fn1.hello.apply(fn2,[1,2,3]); 3 fn1.hello.bind(fn2)(1,2,3);
好消息是,IE8如下並不支持。腫麼辦?
不要緊,大牛們寫好了,咱們來看一下
1 if (!Function.prototype.bind) { 2 Function.prototype.bind = function (oThis) { 3 if (typeof this !== "function") { 4 throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); 5 } 6 var aArgs = Array.prototype.slice.call(arguments, 1), 7 fToBind = this, 8 fNOP = function () {}, 9 fBound = function () { 10 return fToBind.apply(this instanceof fNOP ? this : oThis || this , 11 aArgs.concat(Array.prototype.slice.call(arguments))); 12 }; 13 fNOP.prototype = this.prototype; 14 fBound.prototype = new fNOP(); 15 return fBound; 16 17 }; 18 }
最後:
JS中,函數的使用是很是之靈活,好比閉包、當即函數、等等等等,之後有機會專門討論。