JS中的call()和apply()方法總結
在js中每個函數都包含兩個非繼承而來的方法:call()和apply()
call和apply的作用都是在特定的作用域中將函數綁定到另外一個對象上去運行,即可以用來重新定義函數的執行環境,兩者僅在定義參數方式上有所區別
它們接收參數方麵不同:call和apply的第一個參數都是需要調用的函數對象,在函數體內這個參數就是this的值,剩餘的參數是需要傳遞給函數的值,call與apply的不同就是call傳的值可以是任意的,而apply傳的剩餘值必須為數組
call方法
語法:
Function.call(obj,param1,param2...)
obj:這個對象將替代Function類裏的this對象
params:這是一個參數列表
注意: 調用call的對象必須是一個函數對象,因為 call這個方法是在Function的prototype裏的
定義:
調用一個對象的一個方法,以另一個對象替換當前對象
關於call的定義很拗口。我的理解:a.call(b,arg1,arg2..)就是a對象的方法應用到b對象上
function add(a,b){
alert(a+b);
}
function reduce(a,b){
alert(a-b);
}
add.call(reduce,1,3) //將add方法運用到reduce,結果為4
這個例子中的意思就是用 add 來替換 reduce,add.call(reduce,3,1) == add(3,1) ,所以運行結果為:alert(4); // 注意:js中的函數其實是對象,函數名是對 Function 對象的引用
window.firstName = "diz";
window.lastName = "song";
var myObject = { firstName: "my", lastName: "Object" };
function HelloName() {
console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!");
}
HelloName.call(window); //Hello diz song glad to meet you!
HelloName.apply(myObject); //Hello my Object glad to meet you!
在例子中,我們發現apply()和call()的真正用法是能夠擴充函數賴以運行的作用域,如果我們想用傳統的方法實現,請見下麵的代碼:
window.firstName = "diz";
window.lastName = "song";
var myObject = { firstName: "my", lastName: "Object" };
function HelloName() {
console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!");
}
HelloName(); //Hello diz song glad to meet you!
myObject.HelloName = HelloName;
myObject.HelloName(); //Hello my Object glad to meet you!
我們發現,要想讓HelloName()函數的作用域在對象myObject上,我們需要動態創建myObject的HelloName屬性,此屬性作為指針指向HelloName()函數,這樣,當我們調用myObject.HelloName()時,函數內部的this變量就指向myObject,也就可以調用該對象的內部其他公共屬性了
<input type="text" value="input text">
<script>
function Obj(){this.value="對象!";}
var value="global 變量";
function Fun1(){alert(this.value);}
window.Fun1(); //global 變量
Fun1.call(window); //global 變量
Fun1.call(document.getElementById('myText')); //input text
Fun1.call(new Obj()); //對象!
window.Fun1(); //global 變量
</script>
call可以改變this指向
function Animal(){
this.name=”animal”;
this.showName=function(){
alert(this.name)
}
}
function Cat(){
this.name=”cat”;
}
var animal = new Animal();
var cat = new Cat();
animal.showName(); //結果為animal
animal.showName.call(cat); //通過call方法將原本屬於Animal對象的showName()方法交給對象cat來使用,輸入結果為"Cat"
call 的意思是把 animal 的方法放到cat上執行,原來cat是沒有showName() 方法,現在是把animal 的showName()方法放到 cat上來執行,所以this.name 應該是 Cat
bind()方法
支持此方法的瀏覽器有IE9+、Firefox4+、Safari5.1+、Opera12+、Chrome。它屬於ECMAScript5的方法:
window.color = "red";
var o = { color: "blue" };
function sayColor(){
console.log(this.color);
}
var OSayColor = sayColor.bind(o);
OSayColor(); //blue
這裏,sayColor()調用bind()方法,並傳入o對象,返回了OSayColor()函數,在OSayColor()中,this的值就為o對象
實現繼承
function Animal(name){
this.name=name;
this.showName=function(){
alert(this.name)
}
}
function Cat(name){
Animal.call(this,name);
}
var cat = new Cat(“Black Cat”);
cat.showName(); //瀏覽器彈出Black Cat
Animal.call(this) 的意思就是使用 Animal對象代替this對象,那麼 Cat中不就有Animal的所有屬性和方法了嗎,Cat對象就能夠直接調用Animal的方法以及屬性了
多重繼承
function s1(name){
this.name = name;
}
var s2 = function(sex){
this.sex = sex;
}
var s3 = function(age){
this.age = age;
}
var Student = function(name,sex,age,score){
s1.call(this,name);
s2.call(this,sex);
s3.call(this,age);
this.score = score;
}
Student.prototype.construction = Student;
var s = new Student('jack','male','12','100');
console.log(s.name); //輸出:jack
console.log(s.sex); //輸出:male
console.log(s.age); //輸出:12
console.log(s.score);//輸出:100
很簡單,使用兩個 call 就實現多重繼承了。當然,js的繼承還有其他方法,例如使用原型鏈
當然還有 apply,這兩個方法基本上是一個意思,區別在於 call 的第二個參數可以是任意類型,而apply的第二個參數必須是數組,也可以是arguments
還有 callee,caller..
apply方法:
語法:
Function.apply(obj,args)
obj:這個對象將代替Function類裏this對象(就是定義函數代碼塊裏麵的this)
args:這個是數組,它將作為參數傳給Function(args-->arguments),這個可以是數組也可以是 arguments
定義:
應用某一對象的一個方法,用另一個對象替換當前對象。
什麼情況下用apply,什麼情況下用call
在給對象參數的情況下,如果參數的形式是數組,比如apply示例裏麵傳遞了參數arguments,這個參數是數組類型,並且在調用Animal的時候參數的列表是對應一致的(也就是Animal和Cat的參數列表前兩位是一致的) 就可以采用 apply , 如果我的Animal的參數列表是這樣的(age,name),而Cat的參數列表是(name,age,kind),這樣就可以用call來實現了,也就是直接指定參數列表對應值的位置(Person.call(this,age,name,kind));
apply的一些其他巧妙用法:
apply可以將一個數組默默的解析成一個一個的參數,可以將一個數組默認的轉換為一個參數列表([param1,param2,param3] 轉換為 param1,param2,param3) ,利用aplly這個特點我們就可以用在一些針對字符串操作的方法了:例如
1.Math.max 可以實現得到數組中最大的一項
因為Math.max 參數裏麵不支持Math.max([param1,param2])
也就是數組,但是它支持Math.max(param1,param2,param3…)
,所以可以根據剛才apply的那個特點來解決var max=Math.max.apply(null,array)
,這樣輕易的可以得到一個數組中最大的一項 (apply會將一個數組裝換為一個參數接一個參數的傳遞給方法) 這塊在調用的時候第一個參數給了一個null,這個是因為沒有對象去調用這個方法,我隻需要用這個方法幫我運算,得到返回的結果就行,.所以直接傳遞了一個null過去(利用Math方法但是不改變this的指向)
2.Math.max 可以實現得到數組中最小的一項
和 max是一個原理 var min=Math.min.apply(null,array)
3.Array.prototype.push 可以實現兩個數組合並
arr1=new Array("1","2","3");
var arr2=new Array("4","5","6");
Array.prototype.push.apply(arr1,arr2);
最後更新:2017-06-20 17:02:26