對js中Function的淺見

它究竟是什麼算法

String Array 都是系統內置對象(已經定義好,能夠直接使用)固然,這貨也是同樣,咱們以前定義的函數,其實就是一個這貨的實例。數組

JS中,全部的對象都是由函數實現的,函數的數據類型是objectSo,咱們之前定義的函數也是一個對象。閉包

 

幾種寫法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:這個是數組,它將做爲參數傳給Functionargs-->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對象上。

 contructorprototype屬性是系統自動生成的。但本質上只是是函數對象的屬性而已。

對象是一個函數,而函數對象含有contructorprototype等屬性,

那麼實例化的過程就是拷貝構造函數屬性的過程,因此每一個實例天然就擁有了contructorprototype這兩個屬性。

 

自定義對象:函數實現的--函數又是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中,函數的使用是很是之靈活,好比閉包、當即函數、等等等等,之後有機會專門討論。

相關文章
相關標籤/搜索