天天看點

第195天:js---函數對象詳解(call、apply)

一、call

1、call供爺法則

1 //    對象1
 2    var myclass={
 3     getAllStudentsNumbers:function(num1,num2){
 4         return num1+num2;
 5   }};
 6 //   對象2
 7     var student={
 8        getDetail:function(){
 9            return {name:'樂樂',like:'唱歌跳舞'}
10        }
11    };
12     //借用 供爺法則 student可以借用myclass的方法
13     //call和apply的差別 傳參的不同
14     //call是所有參數平鋪,apply是将參數放在數組中進行傳遞
15     console.log(myclass.getAllStudentsNumbers.call(student,10,20));//30
16     console.log(myclass.getAllStudentsNumbers.apply(student,[10,20]));//30      
1 //函數其實也是對象
 2     function add(a, b)
 3     {
 4         console.log(a + b);
 5     }
 6     function sub(a, b)
 7     {
 8         console.log(a - b);
 9     }
10     add.call(sub, 3, 1);//4      

2、call---this

1  /*定義一個animal類*/
 2     function Animal(){
 3         this.name = "Animal";
 4         this.showName = function(){
 5             alert(this.name);
 6         }
 7     }
 8     /*定義一個Cat類*/
 9     function Cat(){
10         this.name = "Cat";
11     }
12 
13     /*建立兩個類對象*/
14     var animal = new Animal();
15     var cat = new Cat();
16 
17     //通過call或apply方法,将原本屬于Animal對象的showName()方法交給目前對象cat來使用了。
18     //輸入結果為"Cat"
19     animal.showName.call(cat,",");//Cat
20     //animal.showName.apply(cat,[]);      

3、call使用場景---數組化

将僞數組轉換為數組:

var domNodes =  Array.prototype.slice.call(divs);      
1 /*僞數組:隻有數組的部分功能:length,下标,無法通路數組對象中的方法*/
 2     var divs = document.getElementsByTagName("div")
 3     console.log(divs.length);
 4     /*說明他不是一個數組,無法通路裡面的方法*/
 5 //    divs.pop().style.background='green'
 6 
 7     /*我們通過如下方式将其轉換成數組*/
 8     var domNodes =  Array.prototype.slice.call(divs);
 9     /*這樣domNodes就可以應用Array下的所有方法了。*/
10 
11 
12     /* slice : 截取數組,傳回的還是數組,這裡我們截取全部  */
13     domNodes.pop().style.background='green';      

二、apply

1、基本用法

1  /*定義一個人類*/
 2     function Person(name,age) {
 3         this.name=name;
 4         this.age=age;
 5     }
 6 
 7     /*定義一個學生類*/
 8     function Student(name,age,grade) {
 9         Person.apply(this,arguments);
10         this.grade=grade;
11     }
12 
13     //建立一個學生類
14     var student=new Student("鄧樂樂",24,"一年級");
15     //測試
16     document.write("姓名:"+student.name+"\n"+"年齡:"+student.age+"\n"+"年級:"+student.grade);//姓名:鄧樂樂 年齡:24 年級:一年級
17     //大家可以看到測試結果name:鄧樂樂  age:24  grade:一年級
18     //學生類裡面我沒有給name和age屬性指派啊,為什麼又存在這兩個屬性的值呢,這個就是apply的神奇之處.
19 
20     //分析: Person.apply(this,arguments);
21     //
22     //this:在建立對象在這個時候代表的是student
23     //
24     //arguments:是一個數組,也就是[“鄧樂樂”,”24”,”一年級”];
25     //
26     //也就是通俗一點講就是:
27     //   用student去執行Person這個類裡面的内容,    在Person這個類裡面存在this.name等之類的語句,
28     //   這樣就将屬性建立到了student對象裡面      

2、巧妙用法

(1)Max函數用法

1 // apply的一些其他巧妙用法
 2     // 細心的人可能已經察覺到,在我調用apply方法的時候,
 3     // 第一個參數是對象(this),
 4     // 第二個參數是一個數組集合,
 5     // 在調用Person的時候,他需要的不是一個數組,
 6     // 但是為什麼他給我一個數組我仍然可以将數組解析為一個一個的參數,
 7     // 這個就是apply的一個巧妙的用處:可以将一個數組預設的轉換為一個參數清單([param1,param2,param3] 轉換為 param1,param2,param3) 這個如果讓我們用程式來實作将數組的每一個項,來轉換為參數的清單,
 8     // 可能都得費一會功夫,借助apply的這點特性,是以就有了以下高效率的方法:
 9 
10     // max函數用法
11     // Math.max後面可以接任意個參數,最後傳回所有參數中的最大值。
12         console.log(Math.max(5,8))   //8
13         console.log(Math.max(5,7,9,3,1,6))   //9
14 
15     //但是在很多情況下,我們需要找出數組中最大的元素。
16 
17 var arr=[5,7,9,1]
18 alert(Math.max(arr))    //這樣卻是不行的。因為其不支援傳遞數組過去 那麼怎麼做呢,就要考察我們的算法功底了。。
19 
20 function getMax(arr){
21     var arrLen=arr.length;
22     for(var i=0,ret=arr[0];i<arrLen;i++){
23         ret=Math.max(ret,arr[i]);
24     }
25     return ret;
26 }
27 
28 
29 //擷取數組中的最大值
30     var max=Math.max.apply(null,[1,10,122,3335,333,34343,34343,5657767,2,34455,445466,45454,343434,46466,56556,464646,464646,466,4646464])
31     alert('最大值:'+max);
32 
33 // 整體解析:
34 // 因為Math.max 參數裡面不支援Math.max([param1,param2]) 也就是數組
35 // 但是它支援Math.max(param1,param2,param3…),是以可以根據剛才apply的那個特點來解決
36 // var max=Math.max.apply(null,array),這樣輕易的可以得到一個數組中最大的一項
37 // (apply會将一個數組裝換為一個參數接一個參數的傳遞給方法)
38 // 第一個參數為什麼是null:
39 // 這塊在調用的時候第一個參數給了一個null,這個是因為沒有對象去調用這個方法,
40 // 我隻需要用這個方法幫我運算,得到傳回的結果就行,.是以直接傳遞了一個null過去      

(2)Min計算最小值

1 //計算最小值
 2       var min=Math.min.apply(null,[1,10,122,3335,333,34343,34343,5657767,2,34455,445466,45454,343434,46466,56556,464646,464646,466,4646464]);
 3       alert('最小值:'+min);//1
 4 
 5 //Math.min  可以實作得到數組中最小的一項
 6 //同樣和 max是一個思想
 7 
 8 
 9 // Array.prototype.push 可以實作兩個數組合并
10 // 同樣push方法沒有提供push一個數組,但是它提供了push(param1,param,…paramN)
11 // 是以同樣也可以通過apply來裝換一下這個數組,即:
12 
13         var arr1=new Array("1","2","3");
14         var arr2=new Array("4","5","6");
15         Array.prototype.push.apply(arr1,arr2);
16         alert(arr1);//1,2,3,4,5,6
17         alert(arr2);//4,5,6
18 //也可以這樣了解,arr1調用了push方法,參數是通過apply将數組裝換為參數清單的集合.
19 
20 
21 //     傳統寫法
22       function PushArray(arr1,arr2){
23           var arrLen=arr2.length
24           for(var i=0;i<arrLen;i++){
25               arr1.push(arr2[i])
26           }
27           return arr1;
28       }
29         var result = PushArray(arr1,arr2);
30         console.log(result);//Array(9)      

3、apply實作繼承

1 // apply實作繼承
 2 // 學生類本來不具備任何方法,
 3 // 但是在 Person.apply(this,arguments)  後,
 4 // 他就具備了 Person類的sayhello方法和 所有屬性。
 5 // 在 Print.apply(this,arguments) 後就自動得到了  show() 方法。
 6 
 7 
 8     //人對象
 9     function Person(name,age){   //定義一個類,人類
10         this.name=name;     //名字
11         this.age=age;       //年齡
12         this.sayhello=function(){console.log("人對象的某個方法")}
13     }
14 
15     //輸出列印對象
16     function Print(){            //顯示類的屬性
17         this.funcName="我是列印對象";
18         this.show=function(){
19            console.log ('列印對象的某個方法');
20         }
21     }
22 
23     //學生對象
24     function Student(name,age,grade,school){    //學生類
25         Person.apply(this,arguments);
26         Print.apply(this,arguments);
27         this.grade=grade;                 //年級
28         this.school=school;                    //學校
29     }
30 
31 // 執行個體化人對象
32     var zhangsan=new Person("張三",10)
33     zhangsan.sayhello();
34 
35 // 執行個體化學生對象
36     var lisi=new Student("tom",13,6,"清華國小")
37 // 學生繼承了人和列印對象,則擁有了人的屬性和方法
38     lisi.show();//列印對象的某個方法
39     lisi.sayhello();//人對象的某個方法
40     console.log(lisi.funcName);//我是列印對象      

繼續閱讀